Using the knockout mapping plugin ( http://knockoutjs.com/documentation/plugins-mapping.html ) can you map a deeply hierachical object?
If I have an object with multiple levels:
var data = {
name: 'Graham',
children: [
{
name: 'Son of Graham',
children: [
{
name: 'Son of Son of Graham',
children: [
{
... and on and on....
}
]
}
]
}
]
}
How do I map it to my custom classes in javascript:
var mapping = {
!! your genius solution goes here !!
!! need to create a myCustomPerson object for Graham which has a child myCustomerPerson object
!! containing "Son of Graham" and that child object contains a child myCustomerPerson
!! object containing "Son of Son of Graham" and on and on....
}
var grahamModel = ko.mapping.fromJS(data, mapping);
function myCustomPerson(name, children)
{
this.Name = ko.observable(name);
this.Children = ko.observableArray(children);
}
Can the mapping plugin recursively map this data into an hierachy of my custom objects?
From my experience, I would say that it shouldn't have any problems.
I would use the following line -
Then set a breakpoint on the next line at look at the generated object in your debugger (chrome or FF+Firebug works best). This way you will know if ko.mapping will generate a viewmodel that meets your needs.
Normally, it generates an object where only the end points (variables with values) are ko.observables. Any of the other data times that you can use for navigation through the data, like
... children: [...
are shown as ordinary javaScript objects.Something like this (Live copy on js fiddle):
CSS:
HTML:
JavaScript:
This sample just maps an infinitely nested set of JSON data, and I can say from actually using this exact code in application that is works great.
Some of the extra functions like
selectBackNode and selectParentNode
allow you to move back up the tree.
While navigating the example the parent label becomes a link to allow for going up one level, and some of the leaf nodes have a back button that allows them to move back up the tree by a given number of levels.
--EDIT--
If your leaf nodes don't have a children array you might get a problem where additional data is introduced that doesn't exist in the model.
If you don't want the nested mappingOptions (creating a ko map object for each node level), you can take advantage of the fact the ko mapping options for create give you access to the parent object. Something like this:
That way you only have 1 copy of the map, in your class prototype (or could be any function). If you want Folder.parent to be an observable as well, you could do
data.parent = parent;
inside the map function and not pass as a parameter to your Folder constructor, or do that inside the folder constructor instead ofself.parent = parent;
I used the approach in this answer to create a hierarchy of checkboxes where nodes with children are collapsible and when you check/uncheck the parent its descendants get checked/unchecked.
View Model
HTML (view)