-1

我正在创建一个电子商务网站,并且我有一个产品类型模型,其中包含我的客户希望销售的每种产品的所有信息。这个产品模型被推送到一个可观察的数组中,通过 foreach: 在屏幕上显示给用户。这一切都很好。

我希望有诸如复选框/单选按钮之类的控件,它们将过滤屏幕上的数组。例如按颜色或大小。如果处理数字或单词的线性数组,阅读教程很简单。我很难将其翻译为与模型一起使用。我想选择例如颜色为红色,然后可观察数组将过滤到数组中 product.color = red 的位置。

任何帮助将不胜感激。

4

2 回答 2

1

对于我们这些试图提供帮助的人来说,更好地了解您正在尝试做什么是非常有用的。请在以后提出问题时分享您的代码,因为这将有助于我们更好地为您提供帮助并减少我们的猜测。无论哪种方式,我都继续创建了一个 jsfiddle 来演示我认为你可能想要的东西。

http://jsfiddle.net/9cVjv/2/

此演示使用淘汰赛可计算来处理过滤。可计算对象是由某个给定函数计算的可观察对象。在我的示例中,我只是使用基本 JS 数组函数执行了一些过滤(使用ko.utils函数可能更好,但我想为不熟悉淘汰赛的人保持清楚)。

JS:

function FilterViewModel() {
    var self = this;

    self.products = ko.observableArray([
        { name: 'widget', color: 'blue', size: 'large' },
        { name: 'wigglit', color: 'red', size: 'large' },
        { name: 'gadget', color: 'yellow', size: 'small' },
        { name: 'wadget', color: 'blue', size: 'large' },
        { name: 'wizzle', color: 'blue', size: 'small' },
        { name: 'fizzle', color: 'green', size: 'small' },
        { name: 'gigglit', color: 'blue', size: 'small' },
        { name: 'fidget', color: 'red', size: 'large' },
        { name: 'midget', color: 'red', size: 'large' },
        { name: 'madget', color: 'blue', size: 'large' },
    ]);
    self.selectedColor = ko.observableArray('');
    self.selectedSize = ko.observable('');

    self.filteredProducts = ko.computed(function () {
        return self.products().filter(function (value) {
            var isInSet = true;

            // if the size doesn't match, don't include this one
            if(self.selectedSize() != '' && self.selectedSize() != null &&
               self.selectedSize() != value.size)
               isInSet = false;

            // if the colors don't match, don't include this one
            if(self.selectedColor() != '' &&
               self.selectedColor() != null && 
               self.selectedColor() != value.color) {
                   isInSet = false;
            }

            return isInSet;
        });
    });

    self.colorOptions = ko.computed(function() {
        var colorChoices = self.products().map(function(value) {
            return value.color;
        }).filter(function(elem, pos, self) {
            return self.indexOf(elem) == pos;
        });

        //combine a blank choice and the colors from products 
        return (['']).concat(colorChoices);
    });
    self.sizeOptions = ko.computed(function() {      
        var sizeChoices = self.products().map(function(value) {
            return value.size;
        }).filter(function(elem, pos, self) {
            return self.indexOf(elem) == pos;
        });

        //combine a blank choice and the sizes from products
        return (['']).concat(sizeChoices);
    });
}

var viewModel = new FilterViewModel();
ko.applyBindings(viewModel);

HTML:

<div class="blockItem">
    <p>Color: 
        <select data-bind="options: colorOptions, value: selectedColor"></select>
    </p>
    <p>Size: 
        <select data-bind="options: sizeOptions, value: selectedSize"></select>
    </p>
</div>
<div class="blockItem">
    <p><b>PRODUCTS</b></p>
    <!-- ko foreach: filteredProducts -->
        <p class="blockItem">
            <b>Name:</b> <span data-bind="text: $data.name"></span>,
            <b>Color:</b> <span data-bind="text: $data.color"></span>,
            <b>Size:</b> <span data-bind="text: $data.size"></span>
        </p>
    <!-- /ko -->
</div>

CSS:

.blockItem {
    border: 2px black solid;
    padding: 2px;
}
于 2013-10-09T14:58:34.537 回答
0

您可以使用ko.utils函数来过滤您的数组,该页面上的示例只有一个过滤器。如果你想扩展它以过滤不同的字段,那不会太难,但正如 Aeolos 在评论中所说,我们需要你发布一些代码来帮助解决这个问题。

但是,您可以创建一个过滤器对象,其中包含要过滤的字段名称和过滤器值,并将每个活动过滤器添加到过滤器的 observableArray 中:

//filter the items using the filter text
viewModel.filteredItems = ko.computed(function() {
    if (filters().length === 0) {
        return this.items();
    } else {
        var results = this.items();
        for(var i = 0; i < filters().length; i++)
        {
            var filter = filters()[i];
            results = ko.utils.arrayFilter(results, function(item) {
            return ko.utils.stringStartsWith(item[filter.name]().toLowerCase(), filter.value);
            });
        }
        return results;
    }
}, viewModel);

这没有经过任何测试,但它可能会让您知道该怎么做。

于 2013-10-09T14:27:46.923 回答