Jonathan Sayce
Jonathan Sayce

Reputation: 9659

Knockout - display progress image during rendering

I have a page using Knockout to display a filtered list. The view model has an array of objects, and a ko.computed that uses ko.utils.arrayFilter to filter the array.

Occasionally the filtering can get quite complex and take a while, so I'd like to display a progress image to show that something is going on and the world hasn't come to an end.

What's the best way to do this? I've tried using an observable on the view model that gets set at the start and end of the filtering method, but that doesn't seem to work.

Or are there events you can use before and after Knockout starts updating?

I'm new to Knockout so there may be something obvious that I've missed!

JS Fiddle here: http://jsfiddle.net/jsayce/pSzSw/, showing my attempt at setting an observable on the filtering method.

Upvotes: 3

Views: 580

Answers (1)

Artem Vyshniakov
Artem Vyshniakov

Reputation: 16465

To make this work you have to run long operation in another thread. You can do this using setTimeout function or use any fancy third-party library for this. Here is quick solution:

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

    self.englishOnly = ko.observable(false);
    self.filtering = ko.observable(false);

    self.cheeses = ko.observableArray([]);
    self.cheeses.push(new cheese('Camembert', false));
    self.cheeses.push(new cheese('Stilton', true));
    self.cheeses.push(new cheese('Brie', false));
    self.cheeses.push(new cheese('Appenzeller', false));
    self.cheeses.push(new cheese('Wensleydale', true));

    self.selectedCheeses = ko.observableArray(self.cheeses());

    self.englishOnly.subscribe(function() {
        self.filtering(true);

        setTimeout(function() {
            var filteredCheeses = ko.utils.arrayFilter(self.cheeses(), function(cheese) {
                createSlowness();
                return cheese.madeInEngland || !self.englishOnly();
            });

            self.selectedCheeses(filteredCheeses);
            self.filtering(false);
        }, 20);
    });

Here is working fiddle: http://jsfiddle.net/pSzSw/6/

Upvotes: 3

Related Questions