zzarbi
zzarbi

Reputation: 1852

Is there a callback for after UI refresh in KnockoutJs?

Not sure the title is self explanatory, but basically I have an array of zip codes

this.zip_codes = ko.observableArray();

At some point I have an ajax call that get a list of zip code to add to the array

$('.spin').spin();
$.ajax(url, {
    data: {
        miles_min: 1,
        miles_max: 20
    }
}).done(function(data) {
    ko.utils.arrayForEach(data, function(value) {
        self.zip_codes.push(value);
    });
    $('.spin').spin(false);
});

This Knockout array is bind to the UI, it's display a list of input tag.

I added a spinner to show activity at the beginning of the Ajax call and I stop the spinning at the end of the Ajax call. The problem is that if I get a lot of data (+100) Knockout take a long time to update the UI. How can I stop the spinner only after Knockout refresh the UI instead of right after the Ajax call? Or is it because of the way I push the value to the array?

Upvotes: 0

Views: 327

Answers (1)

Nathan
Nathan

Reputation: 390

I'd suggest this change to begin with:

$('.spin').spin();
$.ajax(url, {
    data: {
        miles_min: 1,
        miles_max: 20
    }
}).done(function(data) {
    var tmpArray = [];
    ko.utils.arrayForEach(data, function(value) {
        tmpArray.push(value);
    });
    self.zip_codes(tmpArray);
    $('.spin').spin(false);
});

This will push all the values at once. If you don't do it this way, the subscribers to the observable will be notified every time you push a value rather than when the array has been completely updated.

As for your question of doing things after UI update, there isn't any clean way that I've found. Here's what I've done in the past to take care of this:

$('.spin').spin();
$.ajax(url, {
    data: {
        miles_min: 1,
        miles_max: 20
    }
}).done(function(data) {
    var tmpArray = [];
    ko.utils.arrayForEach(data, function(value) {
        tmpArray.push(value);
    });
    self.zip_codes(tmpArray);
    setTimeout(function() {$('.spin').spin(false)}, 0);
});

This seems to let the processor take hold of churning out the HTML before it'll call the function in the setTimeout.

Upvotes: 2

Related Questions