Reputation: 14416
I have a view model and it has some existing properties.
model.prop1 = ko.observable("");
model.prop2 = ko.observable("");
I then map some data on to this model that will update the value of prop1.
var data = {prop1: 'blah'};
ko.mapping.fromJS(data, {}, model);
I now have some inconsistency when I call ko.toJS
and ko.mapping.toJS
with ko.toJS
it is serialising the model as expected to this:
[object Object] {
model: [object Object] {
__ko_mapping__: [object Object] { ... },
prop1: "blah",
prop2: ""
}
}
I have used the mapping plug-in so it has some superfluous data (ko_mapping) that I don't want.
As such I use ko.mapping.toJS
, however this is not serialising all of the properties... only the ones that have been mapped.
It was my understanding that this would serialise everything as ko.toJS
would?
[object Object] {
model: [object Object] {
prop1: "blah"
}
}
Is this expected behaviour or have I found a bug?
JSBin : https://jsbin.com/jupemoneri/6/edit?js,console
Upvotes: 1
Views: 218
Reputation: 39035
What you're explaining is the normal behavior of the mapper, and it has an explanation: when you bind a model to a view, only the existing observable properties will be bound. If you add new observable properties later, it will make no effect. The view will only be aware of the changes of the observbale properties that existed when it was bound.
So you need to modify the way in which you create the model the first time, so that it includes all the neccessary properties. The easiest way to do it is to use a javascript object that has all the properties, mix it with the object received from the server, and then convert it to model with ko.mapping.fromJs
. Something like this:
// This is an empty object with all the excpected properties
var completeObject { a: null, b:null, c: null };
// "Mix in" the properties from the received, incompelte, object:
// An easy way to do it is using jquery https://api.jquery.com/jquery.extend/
$.extend(completeObject,incompleteObjectFromServer);
// Create the view model using the mapping: var model = ko.mapping.fromJs(completeObject);
Once you do this, you'll get a "complete" model, with all the required properties converted into observable properties, so that they all can be bound to the view. When you use the mapping plugin later, these observable properties will be correctly updated, and the view will react to the changes.
Be aware that when you do the mapping, the model, apart from the observables, includes configuration created whne the object was originally mapped, and this configuration will be used in subsequent mappings, when you use ko.mapping.fromJs()
.
There are other possible techniques to get the same results, like:
NOTE: regarding ko.toJS
, it has nothing to do with mapping: it simply retuns a new object in which the observable properties in the provided object are convertes into regular properties, and the rest of the properties are left as they are.
Upvotes: 1