KO Mapping issue with child objects
Asked Answered
M

2

8

I get the following data from the server:

var data =   [{ id: 0, child: { prop1 : 'a', prop2 : 'b' } }   //Child object has data
             ,{ id: 0, child: null } ];    // Child object is null

I'm having some issues after I map the data using the knockout mapping plugin. The issue is that the inner child object is not of the same type.

After executing this:

ko.mapping.fromJS(data, viewModel.data);   

I get that the first object has a child property of type Object with the data. However the second object has a property child of type Observable that when it's unwrapped returns null.

How can I make that in both cases the objects have the same type even one has value and the other one is null. Changing the way the server behaves is not an option. I expect having Object and null or both Observables.

JsFiddle here.

Maddeu answered 6/9, 2013 at 9:40 Comment(0)
W
4

You need to use the create option to tell the mapping plugin how it should map your child property.

So if you want to have having Object and null you need to return null when your child property is null:

var mappingOptions = {
    child: {
        create: function(options) {
            if (!options.data)
                return null;
            return ko.mapping.fromJS(options.data);
        }
    }
}

ko.mapping.fromJS(data, mappingOptions, viewModel.data);  

Demo JSFiddle.

Or if you want them both Observables:

var mappingOptions = {
    child: {
        create: function(options) {
            return ko.observable(ko.mapping.fromJS(options.data));
        }
    }
}

ko.mapping.fromJS(data, mappingOptions, viewModel.data);   
Wage answered 6/9, 2013 at 9:49 Comment(1)
always test the options.data for null value and then return empty ko.observable()Speos
S
0

As mentioned, the solution is mapping options, but make sure to always test the options.data for null value and then return empty ko.observable(), otherwise you are going to have a lot of trouble with binding! I spent a lot of time on finding that.

var mappingOptions = {
    child: {
        create: function (options) {
            return options.data != null ? ko.observable(ko.mapping.fromJS(options.data)) : ko.observable();
        }
    }
}
Speos answered 7/9, 2016 at 21:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.