Search code examples
javascriptjsonknockout.jsknockout-mapping-plugin

Knockout combining multiple json data into single vm


I want to combine multiple json data into a single vm. I read that you can map from js into the model multiple times and it should be merging but on my case, it's not. It's replacing the data.

function Item(ID, Name, Description) {
    this.ID = ko.observable(ID);
    this.Name = ko.observable(Name);
    this.Description = ko.observable(Description);

}

var MasterViewModel = {
    model: ko.observableArray([])

};

$.getJSON(url, function (response) {
    ko.mapping.fromJS(response["TM1.Cube"], Item, MasterViewModel.model);
    ko.mapping.fromJS(response["TM1.Dimension"], Item, MasterViewModel.model);

})

ko.applyBindings(MasterViewModel);

And here is my json data

{ 
    "LogicalName": "TM1.Model",
    "ID": "12345",
    "Name: "Sample",
    "TM1.Cube": [
        {
            "LogicalName": "TM1.Cube",
            "ID": "111111",
            "Name": Assets"
        },  
        {
            "LogicalName": "TM1.Cube",
            "ID": "111112",
            "Name": Finance"
        }
    ],
    "TM1.Dimension": [
        {
            "LogicalName": "TM1.Dimension",
            "ID": "222221",
            "Name": Assets"
        },
        {
            "LogicalName": "TM1.Dimension",
            "ID": "222222",
            "Name": Finance"
        }
    ]
}

and the outcome I expected is like this

{
    "LogicalName": "TM1.Cube",
    "ID": "111111",
    "Name": Assets"
},  
{
    "LogicalName": "TM1.Cube",
    "ID": "111112",
    "Name": Finance"
},
{
    "LogicalName": "TM1.Dimension",
    "ID": "222221",
    "Name": KPI"
},
{
    "LogicalName": "TM1.Dimension",
    "ID": "222222",
    "Name": Default"
}

I have added a jsFiddle http://jsfiddle.net/e1ppj3qc/1/


Solution

  • The mapping plugin can take an existing model but I don't believe it will merge data.

    For example you could map twice like so:

    {one: "yo"} and {two: "dawg"}

    into the same model and you would now have two observables, one() and two()

    But if you was to do this (which you are): {one: ["yo"]} and {one: ["dawg"]}

    it will always overwrite the matched properties. You could instead do the mapping and then simply push into the array that you want to add to like so:

    function pushCubs(dataToPush) {
         ko.utils.arrayPushAll(MasterViewModel.modelcub, dataToPush());
    }
    
    pushCubs(ko.mapping.fromJS(data));
    pushCubs(ko.mapping.fromJS(data2));
    

    http://jsfiddle.net/e1ppj3qc/2/