简体   繁体   English

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

[英]How to filter nested object array with dynamic multiple check boxes in AngularJS. OR with and Filter

I trying to build a product list based on multiple filters. 我试图建立基于多个过滤器的产品列表。 I thought this should be very straight forward but it's not for me at least. 我认为这应该很简单,但至少不适合我。

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

Checkboxes are dynamically generated from respective model eg sizes , colours , categories . 复选框是根据相应的模型动态生成的,例如sizescolourscategories Subcategory checkbozes should perform 'OR' query but cross section it should perform 'AND' query. 子类别检查框应执行“ OR”查询,但横截面应执行“ AND”查询。

basically something like 基本上像

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

problem is generating these filters dynamically. 问题是动态生成这些过滤器。 I also tried with filter in controller as- 我也尝试在控制器中使用过滤器-

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

But couldn't find a way to assign correct value for OrFilterObjects . 但是找不到为OrFilterObjects分配正确值的OrFilterObjects

Now as latest attempt (which is in plunkr) I am trying to use a custom filter. 现在,作为最新尝试(在plunkr中),我尝试使用自定义过滤器。 It's also not returning OR result. 它也不返回或结果。

Right now I am using it as productFilter:search.categories:'categories' if it would have returned OR result then I'd planned to use it as- 现在,我将其用作productFilter:search.categories:'categories'如果它会返回OR结果),那么我打算将其用作-

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

Since I am here seeking help, it would be nice to have like productFilter:search . 因为我在这里寻求帮助,所以很高兴有productFilter:search

I've spent considerable amount of time to find solution of this supposedly simple problem but most of examples use 'non-dynamic' checkboxes or flat objects. 我花了很多时间来找到这个简单问题的解决方案,但是大多数示例都使用“非动态”复选框或平面对象。

May be I am thinking in wrong direction and there is a more elegant and simple Angular way for such scenarios. 可能是我想的方向错误,在这种情况下有一种更优雅,更简单的Angular方法。 I would love to be directed towards any solution to similar solution where nested objects can be filtered with automated dynamically generated filters. 我很乐意针对类似解决方案的任何解决方案,其中可以使用自动动态生成的过滤器来过滤嵌套对象。 Seems to me very generic use case for any shopping application but till now no luck getting there. 在我看来,任何购物应用程序都具有非常通用的用例,但到现在为止还没有运气。

First thing you need to understand: this problem is not, by any definition, simple. 您需要了解的第一件事:从任何定义上讲,这个问题都不简单。 You want to find a match based on a property of an object in an array which is a property of an object inside an input array you're supplying, not to mention [OR intra group] + [AND inter group] relations, search properties defined by either .title or .name , as well as criteria selection being completely dynamic. 您想基于数组中对象的属性找到匹配项,该属性是您要提供的输入数组中对象的属性,更不用说[OR组内] + [AND组间]关系,搜索属性由.title.name定义,并且条件选择是完全动态的。 It's a complex problem. 这是一个复杂的问题。

Though it's a common scenario for shopping cart websites, I doubt that any web framework will have this kind of functionality built into its API. 尽管这是购物车网站的常见情况,但我怀疑任何Web框架都将在其API中内置这种功能。 It's unfortunate but I don't think we can avoid writing the logic ourselves. 不幸的是,但我认为我们不能避免自己编写逻辑。

At any rate, since ultimately you want to just declare productFilter:search , here it is: 无论如何,由于最终您只想声明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;
    };
});

A couple of notes: 一些注意事项:

  • How to use: ng-repeat="product in products | productFilter:search" . 如何使用: ng-repeat="product in products | productFilter:search"
  • The filter only does some basic checks: input must be an array, and definition must be an object. 过滤器仅进行一些基本检查: input必须是数组, definition必须是对象。 If you need more, you may do so there. 如果您需要更多,可以在那做。
  • I would say that *.name is an exception to the rule (I assume that most of the criteria is defined by *.title ). 我会说*.name是该规则的一个例外(我假设大多数条件都是由*.title定义的)。 So, we handle that in if/else . 因此,我们在if/else
  • The count variable in a helper function is used to track how many checked checkbox(es) we went through for a particular criteria group. helper函数中的count变量用于跟踪特定标准组中经过了多少个选中的复选框。 If we went through none, it means that whole criteria group is inactive , and we just return true . 如果不进行任何操作,则意味着整个条件组都处于非活动状态 ,而我们只返回true
  • It's a good design to create a filter that doesn't mutate the states of other objects outside it. 创建一个不会改变其外部其他对象状态的filter是一个很好的设计。 That's why using count is better than calling cleanObj() . 这就是为什么使用count优于调用cleanObj() This is especially crucial when designing common components for other devs to use in a team: you want to minimize the element of surprise as much as possible. 在设计供团队中其他开发人员使用的通用组件时,这一点尤为重要:您希望尽可能减少意外的因素。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM