Knockout.js ko.mapping.toJS not refreshing data in my view
Asked Answered
B

3

6

I fetch a json object from the server and populate my view. I then change the data, push it back to the server. I then fetch a new copy of the data hoping it will refresh my view with any changes. However that doesn't happen. TIA

$(document).ready(function() {
    var customer_id = get_customer_id();
    var data = load_model();
    contract_model = ko.mapping.fromJS(data,{});
    ko.applyBindings(contract_model);
}

function load_model(){
    var url = '/ar/contract_json?contract_id='+get_contract_id();
    var data = '';
    $.ajax({
        type:'GET',
        url:url,
        async:false,
        success: function(returningValue){
            data = returningValue;
        }
    });
    return data;
}

This initial load works fine. I then do some stuff and change one of the observables and push that data back to server. Server gets the update and then I do a new fetch of the data so that view will refresh (i know i can pass back the new data in one step but this in code i haven't refactored yet).

function refresh_data(contract_model){
    var url = '/ar/contract_json?contract_id='+get_contract_id();
    $.post(url,function(data){
        console.log(data);
        ko.mapping.fromJS(contract_model,{},data);
        ko.applyBindings(contract_model);
        console.log(ko.mapping.toJS(contract_model))
    });

}

function refresh_data(contract_model){
    var url = '/ar/contract_json?contract_id='+get_contract_id();
    $.post(url,function(data){
        console.log(data);
        ko.mapping.fromJS(contract_model,{},data);
        console.log(ko.mapping.toJS(contract_model))
    });

}

function push_model(contract_model,refresh){
    var url = '/ar/update_contract';
    var data = {'contract':ko.mapping.toJSON(contract_model)}

    delete data['lines'];
    $.post(url,data,function(return_value){
        if (refresh){
            refresh_data(contract_model);
        };
    });
}

The console messages all show the new data coming back but my view never updates.

Billybillycock answered 16/2, 2012 at 2:26 Comment(0)
A
21

I believe the problem is with the order of parameters you pass into the ko.mapping.fromJS function when you are updating contract_model.

You have:

ko.mapping.fromJS(contract_model,{},data);

you want:

ko.mapping.fromJS(data, {}, contract_model);
Annihilator answered 16/2, 2012 at 2:42 Comment(3)
The KnockOut docs for the Mapping plugin are, IMO, wrong on the syntax for calling ko.mapping.fromJS(...). The docs show the following: ko.mapping.fromJS(data, viewModel), but clearly this should be: ko.mapping.fromJS(data, {}, viewModel)Pals
Spent hours on this. Thank you this was a big help.Flamingo
I also spent hours on this. I owe you a six packDeese
L
3

@seth.miller's answer is correct. You can also leave out the middle "options" parameter if your contract_model is the same one that was mapped earlier. If there are only two arguments, ko.mapping.fromJS checks if the second argument has a "__ko_mapping__" property. If so, it treats it as a target, otherwise it treats it as an options object.

Lucienlucienne answered 11/12, 2012 at 16:6 Comment(1)
Ugh this is dumb. If the second argument has no "__ko_mapping__" property and the third argument doesn't exist then it really should treat the second argument as the target.Adrial
A
1

Based upon @DBueno's observation - for anyone using typescript I strongly recommend commenting out this method signature from your knockout.mapping.d.ts file.

// fromJS(jsObject: any, targetOrOptions: any): any;

Yes - just comment it out.

enter image description here

You'll then get a compile time error if you try to do :

ko.mapping.fromJS(item.data, item.target);

and you can replace it with the much safer

ko.mapping.fromJS(item.data, {}, item.target);

Safer because whether or not item.target has been previously mapped (and therfore would have a __ko_mapping__ property) it will always copy the properties.

Adrial answered 13/5, 2015 at 6:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.