如何使用AngularJS中的动态多个复选框过滤嵌套对象数组。或者和和过滤器

时间:2014-07-05 05:20:20

标签: javascript angularjs filter

我尝试根据多个过滤器构建产品列表。我认为这应该是非常直接的,但它至少不适合我。

这是plunkr http://plnkr.co/edit/vufFfWyef3TwL6ofvniP?p=preview

复选框是从相应的模型动态生成的,例如sizescolourscategories。子类别检查表应该执行“或”操作。查询但应该执行的横截面' AND'查询。

基本上像

filter:{categories:selectedcategories1} || {categories:selectedcategories2} | filter:{categories:selectedsizes1} || {categories:selectedsizes2}

问题是动态生成这些过滤器。我也尝试使用控制器中的过滤器作为 -

var tempArr = [{'categories':'selectedvalue1'}, {'categories':'selectedvalue2'}];
var OrFilterObjects = tempArr.join('||');
$scope.products = $filter('filter')($scope.products, OrFilterObjects, true);

但无法找到为OrFilterObjects分配正确值的方法。

现在作为最新尝试(在plunkr中)我正在尝试使用自定义过滤器。它也没有返回OR结果。

现在我将它用作productFilter:search.categories:'categories'如果它已经返回OR结果然后我计划将其用作 -

`productFilter:search.categories:'categories' | productFilter:search.colours:'colours' | productFilter:search.sizes:'sizes'`

因为我在这里寻求帮助,所以最好有productFilter:search

我花了相当多的时间来找到这个所谓的简单问题的解决方案,但大多数例子都使用了非动态的问题。复选框或扁平物体。

可能是我在错误的方向思考,并且对于这样的场景有更优雅和简单的Angular方式。我希望能够针对类似解决方案的任何解决方案,其中嵌套对象可以使用自动动态生成的过滤器进行过滤。对于任何购物应用程序来说,这似乎是非常通用的用例,但到目前为止还没有运气。

1 个答案:

答案 0 :(得分:1)

首先需要了解的是:从任何定义来看,这个问题都不简单。您希望根据数组中对象的属性找到匹配项,该数组是您提供的输入数组内对象的属性,更不用说[OR intra group] + [AND inter group]关系,搜索由.title.name定义的属性,以及完全动态的条件选择。这是一个复杂的问题。

虽然这是购物车网站的常见场景,但我怀疑任何网络框架都会在其API中内置这种功能。这很不幸,但我不认为我们可以避免自己编写逻辑。

无论如何,因为最终你想宣布productFilter:search,所以它是:

app.filter('productFilter', function($filter) {
    var helper = function(checklist, item, listName, search) {
        var count = 0;
        var result = false;
        angular.forEach(checklist, function(checked, checkboxName) {
            if (checked) {
                count++;
                var obj = {};
                obj[search] = checkboxName;
                result = result || ($filter('filter')(item[listName], obj, true).length > 0);
            }
        });
        return (count === 0) || result;
    };

    return function(input, definition) {
        var result = [];

        if (angular.isArray(input) && angular.isObject(definition)) {
            angular.forEach(input, function(item) {
                var matched = null;
                angular.forEach(definition, function(checklist, listName) {
                    var tmp;
                    if (listName !== 'colours') {
                        tmp = helper(checklist, item, listName, 'title');
                    } else{
                        tmp = helper(checklist, item, listName, 'name');
                    }
                    matched = (matched === null) ? tmp : matched && tmp;
                });
                if (matched) result.push(item);
            });
        }
        return result;
    };
});

几点说明:

  • 使用方法:ng-repeat="product in products | productFilter:search"
  • 过滤器仅执行一些基本检查:input必须是数组,definition必须是对象。如果你需要更多,你可以在那里。
  • 我会说*.name是规则的一个例外(我假设大部分标准都由*.title定义)。所以,我们在if/else
  • 处理
  • count函数中的helper变量用于跟踪我们针对特定条件组检查的复选框的数量。如果我们没有通过,则表示整个条件组无效,我们只返回true
  • 创建一个不会改变其他对象状态的filter是一个很好的设计。这就是为什么使用count比调用cleanObj()更好的原因。在为团队中使用的其他开发人员设计通用组件时,这一点尤其重要:您希望尽可能减少意外因素。