2015-05-29 4 views
4

У меня есть скрытое поле в шаблоне нокаута, которое его значение обновляется с помощью jquery. Проблема в том, что при попытке передать это значение серверу с помощью ajax, я получаю нулевое значение в контроллере. Но исходный код html показывает, что значение скрытого поля обновляется. Если бы я заменил скрытое поле текстовым полем, это будет нормально работать только при вводе текста вручную.knockoutjs data bind скрытое значение поля

JQuery

 function getFileDetail(fileID, fileName) { 
     $('#hdnFileName' + fileID).val(fileName); 
     $('#lblFileName' + fileID).text(fileName); 
    } 

Вот шаблон HTML Нокаут:

<script type="text/html" id="fileTemplate"> 
     <div data-role="fieldcontain"> 
      <a href="#" data-bind="click: function() { openFileUpload('file', ID) }"><label data-bind="text: 'File Upload ' + ID, attr: { id: 'lblFileName' + ID }"></label></a><input type="button" value="Remove" data-bind="click: removeFile" /> 
     </div> 
     <input type="hidden" name="hdnFileName" data-bind="attr: { id: 'hdnFileName' + ID, value: fileName }" /> 
    </script> 

ViewModel

function FileViewModel() { 
     var self = this; 
     self.ID = ko.observable(); 
     self.fileName = ko.observable(); 
     self.removeFile = function (file) { }; 
     self.Files = ko.observableArray([{ ID: 1, fileName: "", removeFile: function (file) { self.Files.remove(file); }}]); 

     self.addNewFile = function() { 
      var newFile = new FileViewModel(); 
      newFile.ID = self.Files().length + 1; 
      newFile.fileName = ""; 
      newFile.removeFile = function (file) { self.Files.remove(file); }; 
      self.Files.push(newFile); 
      //$("input[name='hdnFileName'").trigger("change"); 
     } 
    } 
function ViewModel() { 
     var self = this; 
     self.fileViewModel = new FileViewModel(); 
     self.submitForm = function() { 

      $.ajax({ 
       type: "POST", 
       url: "<%= Url.Action("MeetingPresenter")%>", 
       data: "{Files:" + ko.utils.stringifyJson(self.fileViewModel.Files) + "}", 
       contentType: "application/json", 
       success: function (data) {}, 
      }); 
     }; 
    } 
+0

Где вы вставляете значение с помощью 'jQuery'? – adricadar

+1

Кажется странным, что вы используете привязку attr для привязки значения. Есть ли причина, по которой вы не используете привязку значения? –

+0

@adricadar Я только что добавил jQuery –

ответ

0

Если вы используете knockout.js вы не Neede изменить DOM, вы можете просто обновить ViewModel и DOM будет обновляться по

function getFileDetail(fileID, fileName) { 
    viewModel.fileViewModel.update(fileID, fileName); 
} 

Добавить update в FileViewModel

function FileViewModel() { 
    // rest of the code 

    self.update = function(fileID, fileName) { 
     var file = ko.utils.arrayFirst(self.Files(), function(file) { 
      return file.ID == fileID; 
     }); 

     file.fileName(fileName); // this will change and the UI will be updated according 
    }; 
} 

Примечание: Пожалуйста, обратите внимание, что у вас есть пункт по умолчанию в Files, который не будет изменен с update функции, поскольку свойства не observable

self.Files = ko.observableArray([{ ID: 1, fileName: "", removeFile: function (file) { self.Files.remove(file); }}]); 

Вы можете решить эту проблему, сделав их observable (т.е. ID: observable(1)) или вы можете создать new FileViewModel().

Примечание:viewModel должен быть в подъезде функции (то есть глобальный экземпляр), в противном случае будет undefined.

+0

Я добавил функцию обновления в FileViewModel, но по какой-то причине файл имеет значение null. Я что-то упускаю? –

+0

@ WS84 Идея состоит в том, чтобы найти элемент, соответствующий условию. Вы можете найти другие способы найти элемент, соответствующий этому условию. Также вы можете поставить brakepoin, чтобы убедиться, что 'fileID' содержит то, что вы хотите, и массив имеет этот элемент. – adricadar

+0

Теперь он работает отлично! Мне просто нужно создать глобальный экземпляр ViewModel(). Благодаря! –

3

Ваша модель свойство ID является наблюдаемой, так что вам нужно «разворачивать ', чтобы получить значение от него, когда y НУ конкатенация, как это:

<input type="hidden" name="hdnFileName" data-bind="attr: { id: 'hdnFileName' + ID(), value: fileName }" /> 

и это:

<label data-bind="text: 'File Upload ' + ID(), attr: { id: 'lblFileName' + ID() }"></label> 
+0

Спасибо David. Но я попробовал это, и он дал ошибку ID() не является функцией. –

0

Мне кажется, что установка значения в поле, через DOM не взаимодействует с нокаутом. Если вы устанавливаете его значение с помощью .value, наблюдаемый не будет обновляться. Вы должны обновлять наблюдаемые.

Я написал немного Fiddle, чтобы продемонстрировать. Каждые 2 секунды он устанавливает значение входа через DOM, но наблюдаемая граница изменяется только при вводе чего-либо.

http://jsfiddle.net/qcv01h2e/

var viewModel = (function() { 
    return { 
     fv: ko.observable().extend({notify:'always'}) 
    }; 
}()); 

ko.applyBindings(viewModel); 
setInterval(function() { 
    console.debug("Set it"); 
    var f = document.getElementById('field'); 
    f.value = "Hi"; 
    console.debug("fv is", viewModel.fv()); 
}, 2000); 
0

Я столкнулся с аналогичной проблемой, где мне нужно установить значение без ввода пользователем. Перед выполнением функции обновления клика я делаю требуемое обновление модели. Если у вас есть режим, лучше ввести функцию в модель.

<input data-bind="click: function(){ isEnabled(true); update() }" /> 

То, что я на самом деле был,

<input data-bind="click: function(){ isEnabled(!isEnabled()); update() }" /> 

Имейте в виду, что асинхронной природы JavaScript.

Смежные вопросы