Knockoutjs - ko.mapping.fromJS не работает

Я только что начал попробовать knockout.js. Ko.mapping предлагает отличный способ получить и отобразить данные с сервера. Однако я не могу заставить отображение работать.

У меня есть простая модель:

//var helloWorldModel;
var helloWorldModel = {
    name: ko.observable('Default Name'),
    message: ko.observable('Hello World Default')
};


$(document).ready(function() {
  ko.applyBindings(helloWorldModel);
      //a button on the form when clicked calls a server class 
      //to get json output
  $('#CallServerButton').click(getDataFromServer);
});

function getDataFromServer() {
  $.getJSON("HelloSpring/SayJsonHello/chicken.json", function(data) { 
    mapServerData(data);
  });
}

function mapServerData(serverData) {
  helloWorldModel = ko.mapping.fromJS(serverData, helloWorldModel);
  alert(JSON.stringify(serverData));
}

У helloWorldModel есть только 2 атрибута - то же самое, что я возвращаюсь с сервера. Предупреждение в mapServerData показывает -

{"name":"chicken","message":"JSON hello world"}

Я просмотрел другие сообщения, касающиеся аналогичной проблемы, но никто из них, похоже, не решил эту проблему. Может быть, мне не хватает чего-то очень элементарного - интересно, может ли кто-нибудь указать это.

Также обратите внимание, если я не объявляю модель upfront и использую

 helloWorldModel = ko.mapping.fromJS(serverData);

он правильно отображает данные в мою форму.

Ответ 1

От Ричарда ответ, а затем немного больше исследований в этом, я думаю, что способ, которым я инициализировал модель, неверен. Я предполагаю, что нельзя использовать существующую модель представления, а затем ожидать, что она будет работать с плагином mapper. Таким образом, вместо этого вы инициализируете модель представления с необработанными данными JSON, используя ko.mapping.fromJS:

var helloWorldModel;

$(document).ready(function() {
  var defaultData = {
      name: 'Default Name',
      message: 'Hello World Default'
  };

  helloWorldModel = ko.mapping.fromJS(defaultData);
  ko.applyBindings(helloWorldModel);
  $('#CallServerButton').click(getDataFromServer);
});

function getDataFromServer() {
  $.getJSON("HelloSpring/SayJsonHello/chicken.json", function(data) { 
    mapServerData(data);
  });
}

function mapServerData(serverData) {
  alert(JSON.stringify(serverData));
  ko.mapping.fromJS(serverData, helloWorldModel);
}

Этот код работает и обеспечивает ожидаемое поведение

Ответ 2

Вы не можете просто перезаписать свою модель, переназначив ее таким образом.

Когда вы выполните:

ko.applyBindings(helloWorldModel);

Вы говорите "привяжите модель helloWorldModel к странице". Нокаут затем просматривает и подключает наблюдаемые в этой модели и связывает их со страницей.

Теперь, когда вы перезаписываете модель формы здесь:

helloWorldModel = ko.mapping.fromJS(serverData, helloWorldModel);

Это перезаписывает ваш объект модели с совершенно новым объектом с совершенно новыми наблюдаемыми в нем.

Чтобы исправить это, вам нужно просто изменить эту строку:

ko.mapping.fromJS(serverData, helloWorldModel);

Это касается свойств внутри модели и переназначает их для вас, не перезаписывая вашу модель.