Mike
Mike

Reputation: 25

Updating a knockout observable after an async ajax call using ko.mapping.fromJS

I have a simple use case. I need to call a WS asynchronously and show the returned JSON on the UI. The JSON that I get back is an object with multiple properties. For simplicity, the code below only has one property. Since I have multiple properties, I am using ko.mapping.fromJS to map the JSON to the object properties. It all seems to work, except the fetched data doesn't update on the UI. If I manually update the observable, it works. But not when using ko.mapping.fromJS.

Javascript

function AppViewModel() {
var self = this;
self.firstName = ko.observable("Bert");

$.ajax({
    dataType: 'json',
    async: true,
    type: 'POST',
    url: '/echo/json/',
    data: {
        json: '{"firstName":"Bob1"}'
    }
}).done(function(data) {
    console.log(data);

    //self.firstName(data.firstName);//This works
    self = ko.mapping.fromJS(data); //This doesn't

    console.log(self.firstName());
}).fail(function(jqxhr, textStatus, error) {
    alert('there was an error');
});
}

// Activates knockout.js
var avm = new AppViewModel();
ko.applyBindings(avm);

HTML

<p>First name: <strong data-bind="text: firstName"></strong></p>

You can run the jsfiddle. You will see that this line works

self.firstName(data.firstName);//This works

and this line doesn't work

self = ko.mapping.fromJS(data); //This doesn't

http://jsfiddle.net/texag93/fakdf5Lw/53/

Upvotes: 1

Views: 1455

Answers (1)

JohnnyHK
JohnnyHK

Reputation: 311865

Two things: 1) You need to create your initial view model with ko.mapping.fromJS, and 2) you need to pass your existing view model as a second parameter to fromJS when updating it.

So something like this instead:

// Activates knockout.js
var avm = ko.mapping.fromJS({firstName: 'Bert'});
ko.applyBindings(avm);

$.ajax({
    dataType: 'json',
    async: true,
    type: 'POST',
    url: '/echo/json/',
    data: {
        json: '{"firstName":"Bob1"}'
    }
}).done(function(data) {
    console.log(data);

    ko.mapping.fromJS(data, avm);

    console.log(avm.firstName());
}).fail(function(jqxhr, textStatus, error) {
    alert('there was an error');
});

Updated fiddle: http://jsfiddle.net/fakdf5Lw/56/

Upvotes: 1

Related Questions