Search code examples
javascriptknockout.jsfilteringknockout-2.0

Multiple filters in knockout.js


Say I have movies array, if I wanted to filter by genre I can do something like this

filtered = ko.computed(function() {
        var self = this;

        if ( ! self.genresFilter() || self.genresFilter() === 'all') {
            return this.sourceItems();
        } else {
            return ko.utils.arrayFilter(self.sourceItems(), function(item) {
                return app.utils.inArray(item.genre, self.genresFilter());     
            });
        }
    }, app.viewModels.games);

But where I'm stuck currently is if I had genres, language and length html dropdowns how can I filter the movies efficiently by all or some of those filters, so that I can have russian action movies or action movies of 90 min length etc?


Solution

  • You'll need to gradually build a filtered list based off of each filter provided. As for the filters themselves, they should either each be represented by an observable or all of them inside an observableArray. This is important because it will trigger the computed to update as you change your filters.

    Example:

    var filteredList = ko.computed({
        var currentList = this.sourceItems();
        var currentFilters = this.genresFilters();
    
        ko.utils.arrayForEach(currentFilters, function () {
            currentList = ko.utils.arrayFilter(currentList, function(filter) {
                return app.utils.inArray(filter, currentFilters);     
            });
        });
    
        return currentList;
    });
    

    This code will loop through each filter, take the latest filtered list and only keep the items that satisfy all conditions.