Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

KnockoutJS - Using custom bindings to add animation

Tags:

knockout.js

I'd like to make use of custom bindings to display a progress icon (spinner or bar) whilst a price is being updated via an ajax call.

Before I started using Knockout I just called onUpdating() at the start of my ajax method and then onUpdated(price) when the ajax successfully returned a price.

function onUpdating() {
    $(".price").empty().html('<img src="/Content/Img/Site/progress.gif" />');
}

function onUpdated(price) {
    $(".price").empty().html('£' + price);
}

As I'm now using Knockout I'd like to use the custom bindings but I just cant get my head around how it works.

I guess something like this:

    ko.bindingHandlers.showProgress = {
        init: function (element, valueAccessor) {
            $(element).empty().html('<img src="/Content/Img/Site/progress.gif" />');
        },
        update: function (element, valueAccessor) {
            $(element).empty().html('£' + valueAccessor());
        }
    }

<p>
    Price: <span data-bind="showProgress: price"></span>
</p>

However, this doesn't work at all. Any help greatly appreciated.

EDIT The following seems to be getting there but its not showing the progress bar whilst updating:

    ko.bindingHandlers.showProgress = {
        update: function (element, valueAccessor) {
            $(element).empty().html('<img src="/Content/Img/Site/progress.gif" />');
            var value = ko.utils.unwrapObservable(valueAccessor());
            $(element).empty().html('£' + value);
        }
    }
like image 235
BrightonDev Avatar asked Jan 18 '23 15:01

BrightonDev


1 Answers

I think that an easy way to handle this one is to add something like a loading sub-observable to the observable that you are updating. Then, set loading to true when you are starting your AJAX request. Set loading to false when your data arrives.

Then, you can bind the visibility of your image to yourobservable.loading.

Here is a sample: http://jsfiddle.net/rniemeyer/kyaKc/

Also, one tip about your custom bindings: The binding's update function will only run again when any of the observables that have their value accessed are updated. So, in your case it would only run when price is updated. You could set the price to null before your AJAX request, then in your binding show the loading image when the value is null, otherwise show the actual value of your observable (which you would have updated when your AJAX request succeeded).

like image 112
RP Niemeyer Avatar answered Jan 29 '23 02:01

RP Niemeyer