Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

knockoutjs - ko.mapping.fromJS not working

I have just started trying knockout.js. The ko.mapping offers a nifty way to get and map data from server. However I am unable to get the mapping to work.

I have a simple model:

//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));
}

The helloWorldModel has only 2 attributes - exactly the same thing I return from the server. The alert in mapServerData shows -

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

I have looked up other posts regarding similar problem, but none of them seemed to be solve this issue. Maybe I am missing something very basic - wondering if anyone can point it out.

Also note if I do not declare the model upfront and use

 helloWorldModel = ko.mapping.fromJS(serverData);

it is mapping the data to my form correctly.

like image 531
6ton Avatar asked Feb 21 '14 03:02

6ton


2 Answers

From Richard's reply and then a little more investigation into this I think that the way I was initializing the model is incorrect. I guess that one cannot use an existing view model and then expect it to work with mapper plugin. So instead you initialize view model with raw JSON data using the 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);
}

This code works and provides the expected behavior

like image 144
6ton Avatar answered Sep 29 '22 01:09

6ton


You can't just overwrite your model by reassigning it this way.

When you do:

ko.applyBindings(helloWorldModel);

You are saying "bind the model helloWorldModel to the page". Knockout then goes through and hooks up the observables in that model and binds them with the page.

Now when you overwrite your form model here:

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

It is overwriting your model object with a brand new object with entirely new observables in it.

To fix it you need to change this line to just:

ko.mapping.fromJS(serverData, helloWorldModel);

This takes care of the properties inside the model and reassigns them for you, without overwriting your model.

like image 40
Richard Rout Avatar answered Sep 29 '22 02:09

Richard Rout