Angular.js ng-repeat filter by property having one of multiple values (OR of values)

JavascriptAngularjsAngularjs Ng-RepeatAngularjs Filter

Javascript Problem Overview


Is it possible to filter an array of objects, such that the value of property can be either of a few values (OR condition) without writing a custom filter

This is similar to this problem - Angular.js ng-repeat :filter by single field

But instead of

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

is it possible to do something like this

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

for a sample data as follows-

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

I've unsuccessfully tried

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

Javascript Solutions


Solution 1 - Javascript

Best way to do this is to use a function:

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

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

Alternatively, you can use ngHide or ngShow to dynamically show and hide elements based on a certain criteria.

Solution 2 - Javascript

For me, it worked as given below:

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

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

Solution 3 - Javascript

I thing ng-if should work:

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

Solution 4 - Javascript

In HTML:

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

In Angular:

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

Solution 5 - Javascript

Here is a way to do it while passing in an extra argument:

https://stackoverflow.com/a/17813797/4533488 (thanks to 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>

With the backend:

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

.


And yet another way with an in-template filter only:

https://stackoverflow.com/a/12528093/4533488 (thanks to 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>

Solution 6 - Javascript

I found a more generic solution with the most angular-native solution I can think. Basically you can pass your own comparator to the default filterFilter function. Here's plunker as well.

Solution 7 - Javascript

After not able to find a good universal solution I made something of my own. I have not tested it for a very large list.

It takes care of nested keys,arrays or just about anything.

Here is the github and demo

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>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionYogesh MangajView Question on Stackoverflow
Solution 1 - JavascriptSherlockView Answer on Stackoverflow
Solution 2 - JavascriptAmol ArankeView Answer on Stackoverflow
Solution 3 - Javascriptjrock10View Answer on Stackoverflow
Solution 4 - JavascriptbboyonlyView Answer on Stackoverflow
Solution 5 - JavascriptaeroView Answer on Stackoverflow
Solution 6 - Javascripts.alemView Answer on Stackoverflow
Solution 7 - JavascriptRaj Nandan SharmaView Answer on Stackoverflow