Reputation: 2993
How can I tweak the code below so that ONLY the "viewNotes" property becomes observable?
I have a requirement to read data from the server and apply it to an ObservableArray. Of all of the properties in the data, ONLY the viewNotes properties need to be observable. Everything else does not need 2 way data binding.
Here is the data which comes from the server:
var data = [
{
"itemName": "Item 1",
"notes": "This is item 1",
"viewNotes": false
},
{
"itemName": "Item 2",
"notes": "This is item 2",
"viewNotes": false
}
]
I then data-bind this to the page as follows. The idea is that the data is presented, but the "notes" property is hidden unless the user clicks to view it. This visibility toggle is linked to the viewNotes property - hence it needing to be observable whereas nothing else does.
<div data-bind="foreach: items">
<div data-bind="text: itemName"></div>
<button data-bind="click: $parent.viewTheNotes">View Notes</button>
<div data-bind="if: viewNotes">
<div data-bind="text: notes"></div>
</div>
<hr>
</div>
The problem is that I can't seem to tune the mapping plugin to bring the data into the observableArray with only the "viewNotes" property for each array element as observable. Here is my code:
var mapping = {
"include": ["viewNotes"]
};
ko.mapping.fromJS(data, mapping, self.items);
alert("is viewNotes observable: " + ko.isObservable(self.items()[0].viewNotes));
alert("is itemName observable: " + ko.isObservable(self.items()[0].itemName));
As you can see, the alert boxes tell us that all sub-properties of each array element seem to have been mapped to observables.
How can I tune it so that only the viewNotes properties are observable?
Here is a Fiddle which shows the issue: https://jsfiddle.net/gxreh8sy/27/
Upvotes: 1
Views: 931
Reputation: 4304
The option you're looking for is the "observe" mapping option. From http://knockoutjs.com/documentation/plugins-mapping.html:
If you want the mapping plugin to only create observables of some properties of your JS object and copy the rest, you can specify an array of propertynames to observe:
var mapping = {
'observe': ["propertyToObserve"] } var viewModel = ko.mapping.fromJS(data, mapping);
}
However, in your case the property doesn't exist at the root level because it's on each child of an array of items. So you can either loop first and map each item of the array in the loop, or you can use the "create" mapping option with a callback function to specify a sub-mapping for each child object.
var mapping = {
create: function(options){
return ko.mapping.fromJS(options.data, {observe: "viewNotes"});
}
};
Upvotes: 3