Joshua
Joshua

Reputation: 23

KnockoutJS Filter ObservableArray by another ObservableArry

Lets say I have an viewmodel with an observablearray of products that has an array of categories (Id, Name) on the Product Object. I then also have an observablearray of filters which are just categories. Is there a way that i can find all the products that have all the categories in the filters observable array. So, I need to return all products that have all the categories in the filters array and not just one filter, but the product must contain all the filters. Thanks in advance

Upvotes: 2

Views: 2977

Answers (1)

vadim
vadim

Reputation: 1726

I think it should looks like that:

        function Product(id, name) {
            this.id = id;
            this.name = name;
            this.categories = [];
        }

        function ProductCategory(name) {
            this.name = name;
        }

        function ViewModel() {
            this.products = ko.observableArray();
            this.filters = ko.observableArray();
            var self = this;

            //dummy data
            self.init = function () {
                var c1 = new ProductCategory('Cat1');
                var c2 = new ProductCategory('Cat2');
                var c3 = new ProductCategory('Cat3');
                var c4 = new ProductCategory('Cat4');

                var p1 = new Product(1, 'Prod 1');
                p1.categories = [c1, c2];

                var p2 = new Product(2, 'Prod 2');
                p2.categories = [c1, c3, c4];

                var p3 = new Product(3, 'Prod 3');
                p3.categories = [c3, c4];

                var p4 = new Product(4, 'Prod 4');
                p4.categories = [c1, c2, c4];

                self.products([p1, p2, p3, p4]);
                self.filters([c1, c3, c4]);
            };

            self.init();

            //filtered products will be recalculated on products or filters array change
            self.filteredProducts = ko.computed(function () {
                var filteredProducts = [];
                ko.utils.arrayForEach(self.products(), function (product) {
                    var notInFilter = false;

                    for (var i = 0; i < product.categories.length; i++) {
                        var category = product.categories[i];

                        if (self.filters().indexOf(category) < 0) {
                            notInFilter = true;
                            break;
                        }
                    }

                    if (!notInFilter) {
                        filteredProducts.push(product);
                    }
                });

                return filteredProducts;
            });
        }

Fiddle with code

Upvotes: 3

Related Questions