Search code examples
ajaxknockout.jsknockout-mapping-plugin

knockout mapping (ko.mapping.fromJS()) not updating targets when async $.ajax call


I am trying to use ko.mapping to transform data to a viewmodel. The result come from an async call to a web service.

Simple view:

<div data-bind="with: myData">
    <div data-bind="text: mapWidth"></div>
    <div data-bind="text: mapHeight"></div>
    <div data-bind="foreach: priceRanges">
    <div data-bind="text: title"></div>
</div>

AND the view model is as follows:

var ViewModel = function() {
    var self = this;

    self.myData = null;

    var data = {
        action: 'GetPricePoints',
        type: 'who cares'
    };

    $.ajax({
        url: 'http://cdt.lotamore.com/api/imap',
        data: { "": JSON.stringify(data) },
        //async: false, // works!
        async: true, // doesn't work!!!!!
        type: 'post'
    })
    .done(function (data) {
        self.myData = ko.mapping.fromJS(data);
    })
    .error(function (data) {
        alertError(data);
    })
    .always(function () {
    });
};

When I run this synchronously is works fine. However, when I run it asynchronously it doesn't update the myData within my view model.

I have created a fiddle here: http://jsfiddle.net/jgergen/jF9pm/20/

I really don't want to make ajax calls that block the UI thread! What am I doing wrong here?

Thanks, Jim


Solution

  • Here is the solution:

    I have changed the line:

        self.myData = null;
    

    to:

        self.myData = ko.observable();
    

    This is not all, I tried this before without favorable results. In addition to making myData observable, I had to change the way it is updated. Here is the new .done method:

        .done(function (d) {
            self.myData(ko.mapping.fromJS(d));
        })
    

    So, what I needed to do is treat this field as I would any other observable.

    You can see it here at this new fiddle: http://jsfiddle.net/jgergen/jF9pm/47/

    I hope that this helps more than me. I searched for a solution to this problem all over the web without any results. So here it is.

    Thanks, Jim