Reputation: 27370
What are the differences between the 2?
Surely they are the same thing since an unwrapped observable strips down to a js primitive. So why have ko.toJS or vice-versa?
Also, why is there a ko.mapping.toJS? Does this not effectively do the same as ko.toJS? There seems several functions in knockoutJS which do the same thing but there must be a reason why they exist.
Upvotes: 31
Views: 16612
Reputation: 146208
With respect to ko.mapping.toJS(...)
vs. ko.toJS(...)
This will create an unmapped object containing only the properties of the mapped object that were part of your original JS object. So in other words, any properties or functions that you manually added to your view model are ignored. By default, the only exception to this rule is the _destroy property which will also be mapped back, because it is a property that Knockout may generate when you destroy an item from an ko.observableArray. See the “Advanced Usage” section for more details on how to configure this.
So this means the mapping plugin only converts back things that IT created for you. If you've merged a view model or added computed or even just regular observables they won't make it back to the model.
If you have a hybrid viewmodel (partly mapped and partly manually created) you may be best creating the JSON to send back to the server in a hybrid way.
You can put this on your page to see how the two models differ:
<h2>ko.TOJSON()</h2>
<pre data-bind="text: ko.toJSON($root, null, 2)"></pre>
<h2>ko.mapping.toJS</h2>
<pre data-bind="text: JSON.stringify(ko.mapping.toJS($root), null, ' ')"></pre>
(I wasn't sure how to 'prettify' the response from ko.mapping.toJSON
so I just used JSON.stringify
Upvotes: 7
Reputation: 430
this is how ko.mapping.toJS & ko.toJS:
var viewModelRaw = { prop: 0 };
var viewModel = ko.mapping.fromJS(viewModelRaw);
var _raw = ko.mapping.toJS(viewModel); // = { prop: 0 }
var _rawWithTraces = ko.toJS(viewModel); // = { prop: 0, __ko_mapping__: .... }
As you can see, ko.mapping.toJS() returns a clean JS object reflecting the view model,
Without leaving any knockout properties, while ko.toJS() leaves some knockout properties..
I'm not sure why they did it that way...
Upvotes: 4
Reputation: 17176
There are differences between them.
The ko.toJS takes an object and "opens up" and cleans the object from all observables. It does this for the entire object graph. I behaves much like a serializer which means that you'll run into problems if you have circular references for instance. It uses mapJsObjectGraph internally which is way too complex for me to fully compile in my head right now. However, I tend to use it when I need to post stuff back to the server.
The ko.utils.unwrapObservable simply determines if the value is an observable and if it is, it returns the underlying value. If not it just returns the value. It can be handy if you you are using the mapping plugin for example where you might end up with models that can have both observables and non observables.
The ko.mapping.toJS is the only one on the list that could be suspected to be somewhat duplicated in terms of its functionality. It is used to map a mapped object graph back to its original state. It looks a lot less complex than ko.toJS but I haven't used it (yet) so I honestly can't tell you more about that one. Read more about it here.
Upvotes: 43