【问题标题】:Knockoutjs arrayFilter multiple dropdownsKnockoutjs arrayFilter 多个下拉列表
【发布时间】:2015-11-21 16:11:15
【问题描述】:

我有一个关于 knockoutjs 中的 arrayFilter 的问题,我将如何使用 2 个应该相关的不同下拉列表过滤我的列表,所以如果我选择了一种类型的建筑物但没有区域,我应该显示所有该类型的建筑物,但是如果我在哪里选择建筑选项和区域选项,过滤应该考虑到这一点,我现在已经在原型上工作了 2 天,但无法弄清楚如何在 arrayfilter 中返回正确的项目。

http://jsfiddle.net/vGg2h/138/

目前,我通过视图模型制作了所有模型并粘贴到数据中,并且连接了一个过滤列表,但是我不明白如何通过 foreach 过滤器和 arrayFilter 返回正确的项目,这就是它得到的地方有点模糊。

       self.filteredList = ko.computed(function () {
            var filters = [];
            filters.push(self.selectedBuilding());
            filters.push(self.selectedArea());
           var currentList = [];

            ko.utils.arrayForEach(filters, function (filter) {
                if (typeof filter !== "undefined") {
                 ko.utils.arrayFilter(self.products(), function (item) {
                    if (filter.id == item.areaId || filter.value == item.buildingId) {
                            currentList.push(item);
                        } 
                 });
                }

            });
            return currentList;
        });

提前感谢您的任何回答!

【问题讨论】:

    标签: javascript knockout.js


    【解决方案1】:

    你有两个问题:

    • 您没有正确使用ko.utils.arrayFilter:您必须返回truefalse,具体取决于最终结果中是否应包含和项目。所以你不应该在arrayFilter 中构建你的结果
    • 您总是从完整列表开始,而不是一个接一个地应用过滤器,但是在 arrayFilter 中错误地构建了结果,这导致您的过滤器与 OR 而不是您最初想要的 AND 组合

    您的固定代码如下所示:

    self.filteredList = ko.computed(function () {
        var filters = [];
        filters.push(self.selectedBuilding());
        filters.push(self.selectedArea());
        var currentList = self.products();
    
        ko.utils.arrayForEach(filters, function (filter) {
            if (typeof filter !== "undefined") {
                currentList = ko.utils.arrayFilter(currentList, function (item) {
                    if (filter.id == item.areaId || filter.value == item.buildingId) {
                        return true;
                    }
                });
            }
        });
        return currentList;
    });
    

    演示JSFiddle

    通过重复使用相同的列表更好地查看 AND 过滤,您可以重写代码以分两个单独的步骤进行过滤:

    self.filteredList = ko.computed(function () {
        var currentList = self.products();
        if (self.selectedBuilding())
        {
            currentList = ko.utils.arrayFilter(currentList, function(item) {
                return self.selectedBuilding().value == item.buildingId;
            });
        }
        if (self.selectedArea())
        {
            currentList = ko.utils.arrayFilter(currentList, function(item) {
                return self.selectedArea().id == item.areaId;
            });
        }
        return currentList;
    });
    

    在这段代码中,更清楚的是,您从完整列表开始,然后逐个应用不同的过滤器,进一步过滤原始列表。

    演示JSFiddle

    注意:如果您最初想从一个空列表开始(就像在您的原始代码中一样),那么如果您的所有过滤器都是空的,那么您可以返回一个空数组:

    self.filteredList = ko.computed(function () {
        if (!self.selectedBuilding() && !self.selectedArea())
            return [];
        //...
    };
    

    演示JSFiddle.

    【讨论】:

    • 非常感谢!我已经研究了一段时间,只是无法正确过滤,我启动了整个 foreach 过滤器,这让我很困惑,这个解决方案清晰易读,非常好。我会将此标记为答案。
    • 我最终使用了最后一个选项,因为这比我的初始代码更干净,这对我了解如何更有效地编写此代码非常有帮助,是否可以过滤下拉列表同样,如果其中没有内容,则根本不在列表中显示它们,我尝试在这里提琴。 jsfiddle.net/bxL1e9wo/1 感谢您花费的时间!
    • @JakobKristensen 强烈建议如果您有这些不同但后续的问题,请将它们作为单独的问题提出。在 cmets 中很难正确回答,其他用户可能不会注意到 cmets 中埋藏的问题。另一方面,您的描述不是很清楚,我不确定您如何想象下拉列表的过滤...您是否正在寻找这样的东西:jsfiddle.net/t8ep835u
    • 这是我正在寻找的确切解决方案,下次我将创建一个后续问题,感谢您的澄清。我的尝试看起来有点不同jsfiddle.net/bxL1e9wo/2 但是我喜欢你的方法,非常感谢你帮助解决这些问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-20
    • 2016-08-31
    • 1970-01-01
    • 2015-12-11
    • 1970-01-01
    • 2021-02-25
    • 2013-06-14
    相关资源
    最近更新 更多