[英]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
. 复选框是根据相应的模型动态生成的,例如
sizes
, colours
, categories
。 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: 一些注意事项:
ng-repeat="product in products | productFilter:search"
. ng-repeat="product in products | productFilter:search"
。 input
must be an array, and definition
must be an object. input
必须是数组, definition
必须是对象。 If you need more, you may do so there. *.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
。 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
。 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.