Angular.js ng-repeat 按属性过滤多个值(值的OR)

67

是否可以过滤对象数组,使得属性的值可以是几个值之一(或条件),而无需编写自定义过滤器

这类似于这个问题 - Angular.js ng-repeat: 按单个字段过滤

但不同的是

<div ng-repeat="product in products | filter: { color: 'red' }">

有没有可能做到这样的事情

<div ng-repeat="product in products | filter: { color: 'red'||'blue' }">

对于以下示例数据-

$scope.products = [
   { id: 1, name: 'test', color: 'red' },
   { id: 2, name: 'bob', color: 'blue' }
   /*... etc... */
];

我曾经尝试过,但没有成功

<div ng-repeat="product in products | filter: { color: ('red'||'blue') }">

2
这个链接可能对你有帮助:https://dev59.com/HGUo5IYBdhLWcg3wpg7N - Satpal
请参考我的答案 - https://dev59.com/aV4c5IYBdhLWcg3wucQt#39523973 - Ravindra Vairagi
这个回答解决了你的问题吗?如何在AngularJS中过滤多个值(OR操作) - Vega
7个回答

104

最好的方法是使用一个函数:

<div ng-repeat="product in products | filter: myFilter">

$scope.myFilter = function (item) { 
    return item === 'red' || item === 'blue'; 
};

或者,您可以使用ngHide或ngShow根据特定条件动态显示和隐藏元素。


6
除了使用函数或自定义过滤器外,没有内联完成此操作的方法吗? ngHide会将display设置为none,但是div仍然会被生成并插入到DOM中。无论如何,我认为使用函数是最干净的方式,只是好奇是否有语法可以在内联中指定OR条件。 - Yogesh Mangaj
1
@Sherlock 更精确地说,您应该添加颜色属性:$scope.myFilter = function (item) { return item.color === 'red' || item.color === 'blue'; }; - jDelforge

41

对我来说,它的运作方式如下:

<div ng-repeat="product in products | filter: { color: 'red'||'blue' }">

<div ng-repeat="product in products | filter: { color: 'red'} | filter: { color:'blue' }">

2
这不更像一个“并且”条件吗? - Shikyo

17

我认为ng-if应该起作用:

<div ng-repeat="product in products" ng-if="product.color === 'red' 
|| product.color === 'blue'">

这是有效的,但$index将指向原始数组索引。 - emathias

11

在HTML中:

<div ng-repeat="product in products | filter: colorFilter">

在Angular中:

$scope.colorFilter = function (item) { 
  if (item.color === 'red' || item.color === 'blue') {
  return item;
 }
};

谢谢,但是如果你仔细阅读问题,我想要一个不需要编写自定义过滤器的解决方案 - Yogesh Mangaj

8
这是一种在传递额外参数的情况下完成它的方法: https://dev59.com/eWgt5IYBdhLWcg3w3xPC#17813797(感谢Denis Pshenov)
<div ng-repeat="group in groups">
    <li ng-repeat="friend in friends | filter:weDontLike(group.enemy.name)">
        <span>{{friend.name}}</span>
    <li>
</div>

关于后端:

$scope.weDontLike = function(name) {
    return function(friend) {
        return friend.name != name;
    }
}

.


还有一种方法仅使用模板过滤器:

https://dev59.com/eWgt5IYBdhLWcg3w3xPC#12528093 (感谢mikel)

<div ng:app>
  <div ng-controller="HelloCntl">
    <ul>
       <li ng-repeat="friend in friends | filter:{name:'!Adam'}">
            <span>{{friend.name}}</span>
            <span>{{friend.phone}}</span>
        </li>
    </ul>
</div>


3

我找到了一个更通用的解决方案,它是我所能想到的最本地化的angular解决方案。基本上,您可以将自己的比较器传递给默认的filterFilter函数。这里也有plunker


0

在找不到好的通用解决方案之后,我自己做了一些东西。我还没有测试过它适用于非常大的列表。

它可以处理嵌套键、数组或几乎任何东西。

这里是githubdemo

app.filter('xf', function() {
    function keyfind(f, obj) {
        if (obj === undefined)
            return -1;
        else {
            var sf = f.split(".");
            if (sf.length <= 1) {
                return obj[sf[0]];
            } else {
                var newobj = obj[sf[0]];
                sf.splice(0, 1);
                return keyfind(sf.join("."), newobj)
            }
        }

    }
    return function(input, clause, fields) {
        var out = [];
        if (clause && clause.query && clause.query.length > 0) {
            clause.query = String(clause.query).toLowerCase();
            angular.forEach(input, function(cp) {
                for (var i = 0; i < fields.length; i++) {
                    var haystack = String(keyfind(fields[i], cp)).toLowerCase();
                    if (haystack.indexOf(clause.query) > -1) {
                        out.push(cp);
                        break;
                    }
                }
            })
        } else {
            angular.forEach(input, function(cp) {
                out.push(cp);
            })
        }
        return out;
    }

})

HTML

<input ng-model="search.query" type="text" placeholder="search by any property">
<div ng-repeat="product in products |  xf:search:['color','name']">
...
</div>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接