Reputation: 6894
Using this test code, based on my real project:
var test = ko.mapping.fromJS({ id: 1, kids: [{ name: "sue"}] });
test.kids.push({ name: "tim" });
test.kids.push(ko.mapping.fromJS({ name: "joe" }));
console.log(test);
console.log(test.kids()[0]);
console.log(test.kids()[1]);
console.log(test.kids()[2]);
test.kids()[2].__ko_mapping__ = undefined;
console.log(test.kids()[2]);
The console output in Firebug shows:
Object { __ko-mapping__={...}, id=d(), kids=d() }
Object { name=d() }
Object { name="tim" }
Object { __ko-mapping__={...}, name=d() }
Object { name=d() }
My goal is to add items to the kids
array after the initial mapping of the data, and have those items look identical to the original items added. If I just push an object directly on the array, the properties are not observables. If I push the object using ko.mapping.fromJS
they get an extra __ko_mapping__
object included. I'd rather not have the extra object, as it doesn't seem to be needed (original items don't have it and work fine), and I might use this same design in places where I am adding 1000s of items later.
Setting the object to undefined
does seem to remove the extra object, but would rather not have it created in the first place if possible.
Upvotes: 2
Views: 1251
Reputation: 1
http://knockoutjs.com/documentation/plugins-mapping.html
You can choose which properties get mapped and how.
Upvotes: 0
Reputation: 6894
Based on lack of any other answers, and the only answer being one that is probably a better design practice but actually does the opposite of what I asked for (it adds a mapping object to every child).. I guess I already had the answer in my original question, just assumed there must be a better way.
So for future readers, here it is:
test.kids()[2].__ko_mapping__ = undefined;
Just set ko_mapping to undefined, if you want to get rid of it.
See the comments and other answer as to why this isn't a good idea in-general. For my needs, and maybe you have the same, it is a good idea.
Upvotes: 1
Reputation: 126
I generally find it useful to create a strong prototype for 'Kids' and tell the mapping plugin to use it when mapping your initial data. This would cause the contents of the array to be identical and have the added benefit of permitting computeds and observables for each Kid.
var Kid = function(json){
ko.mapping.fromJS(json, {}, this);
}
var mapping = {
'kids': {
create: function(options) {
return new Kid(options.data);
}
}
}
Now if you have to add items just create new Kids.
var test = ko.mapping.fromJS({ id: 1, kids: [{ name: "sue"}] }, mapping);
test.kids.push(new Kid({ name: "tim" }));
test.kids.push(new Kid({ name: "joe" }));
console.log(test);
console.log(test.kids()[0]);
console.log(test.kids()[1]);
console.log(test.kids()[2]);
Firebug then shows:
Object {id: function, kids: function, __ko_mapping__: Object}
Kid {name: function, __ko_mapping__: Object}
Kid {name: function, __ko_mapping__: Object}
Kid {name: function, __ko_mapping__: Object}
Upvotes: 0