toJSON view model overrides not being reflected after Knockout unmapping
Asked Answered
I

1

0

I have a deep object graph from the server which I am representing with a Knockout view model structure which omits various unnecessary properties at each level but preserves the basic hierarchy.

I'm using the Knockout mapping plugin in both directions. At each view model level below the root, the "constructor" of the current view model accepts its parent view model to keep as a reference, plus the part of the original data necessary to construct itself with. It then creates a new set of mapping options to create its own children.

I've created a heavily simplified fiddle which illustrates this:

http://jsfiddle.net/tqPtG/17/

There is a lot of heavy readonly metadata which I need from the server on retrieval, but should be omitted when I post the graph back as JSON. I've been using the toJSON prototype method at each level to cull what I don't need, and this was working beautifully at one point but has now stopped working.

Locally, it appears that my toJSON overrides do not even fire (based on alerts and console logs), but in this fiddle, they do fire, but the final object still contains the deleted property "child". I can see it being removed by the toJSON method but after the root unmapping it is still there and shown in the alert.

So, 2 questions - what would cause my toJSON overrides to not fire locally, and where is my misunderstanding of the unmapping logic in the simplified fiddle?

Many thanks in advance.

Identification answered 21/6, 2012 at 23:22 Comment(0)
H
2

A couple of things are going on here:

  • your toJSON function is getting called, but not as part of the ko.mapping.toJSON call. The mapping plugin does a stringify as part of determining a key for objects.
  • ko.mapping.toJSON creates a plan copy of the object and at that point it is no longer an instance of ParentViewModel. Then, when it stringifies the object, it will have no reason to run your toJSON function.

The call to ko.mapping.toJSON does support a second argument for options. You could pass { ignore: ['child'] } in as this argument like: http://jsfiddle.net/rniemeyer/4kHC2/

Hester answered 22/6, 2012 at 2:10 Comment(3)
Thanks Ryan. My understanding of the use of toJSON methods on each view model was that you got a chance to implement custom stringification for each sub-component of the total JSON - in the relevant places. Thanks for the tip re the extra argument - but how would I specify ignore properties for each of the sub levels as well? For example if there are properties on ChildViewModel which I need to exclude.Identification
This is generally true for ko.toJSON. It appears that ko.mapping.toJSON handles it a bit differently. So, you could use ko.toJSON and just delete __ko_mapping__ along with any other properties that you don't want. For the ignore array, you can specify and property names that you want excluded, even if they are nested. The only issue would be if you have the same property names at different levels and don't want to ignore at all levels.Hester
Ah excellent, thanks - luckily that ignore list works perfectly for me. However I have a nagging fear of future conflicts. It'd be super cool if ko.mapping.toJSON could look at individual properties' toJSON implementations when it does its thing.Identification

© 2022 - 2024 — McMap. All rights reserved.