Search code examples
knockout.jsknockout-mapping-plugin

knockoutjs mapping, add new item to child array without the extra mapping object


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.


Solution

  • 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.