Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filtering by Multiple Specific Model Properties in AngularJS (in OR relationship)

Tags:

angularjs

Take a look at the example here: http://docs.angularjs.org/api/ng.filter:filter

You can search by any of the phone properties by using <input ng-model="search"> and you can search by just the name by using <input ng-model="search.name">, and the results are appropriately filtered by name (typing in a phone number does not return any results, as expected).

Let's say I have a model with a "name" property, a "phone" property, and a "secret" property, how would I go about filtering by both the "name" and "phone" properties and not the "secret" property? So in essence, the user could type a name or phone number and the ng-repeat would filter correctly, but even if the user typed in a value that equaled part of a "secret" value, it wouldn't return anything.

Thanks.

like image 451
winduptoy Avatar asked Nov 04 '12 04:11

winduptoy


People also ask

What is correct way to apply multiple filters in AngularJS?

Filters can be applied to the result of another filter. This is called "chaining" and uses the following syntax: {{ expression | filter1 | filter2 | ... }} E.g. the markup {{ 1234 | number:2 }} formats the number 1234 with 2 decimal points using the number filter.

Which character is used to chain multiple filters in AngularJS?

The pipe symbol ( | ) is used to chain multiple filters together.


2 Answers

Here is the plunker

New plunker with cleaner code & where both the query and search list items are case insensitive

Main idea is create a filter function to achieve this purpose.

From official doc

function: A predicate function can be used to write arbitrary filters. The function is called for each element of array. The final result is an array of those elements that the predicate returned true for.

<input ng-model="query">  <tr ng-repeat="smartphone in smartphones | filter: search ">  

$scope.search = function(item) {     if (!$scope.query || (item.brand.toLowerCase().indexOf($scope.query) != -1) || (item.model.toLowerCase().indexOf($scope.query.toLowerCase()) != -1) ){         return true;     }     return false; }; 

Update

Some people might have a concern on performance in real world, which is correct.

In real world, we probably would do this kinda filter from controller.

Here is the detail post showing how to do it.

in short, we add ng-change to input for monitoring new search change

and then trigger filter function.

like image 158
maxisam Avatar answered Sep 27 '22 20:09

maxisam


You can pass an Object as the parameter to your filter expression, as described in the API Reference. This object can selectively apply the properties you're interested in, like so:

<input ng-model="search.name"> <input ng-model="search.phone"> <input ng-model="search.secret"> <tr ng-repeat="user in users | filter:{name: search.name, phone: search.phone}"> 

Here's a Plunker

Heads up...this example works great with AngularJS 1.1.5, but not always as well in 1.0.7. In this example 1.0.7 will initialize with everything filtered out, then work when you start using the inputs. It behaves like the inputs have non-matching values in them, even though they start out blank. If you want to stay on stable releases, go ahead and try this out for your situation, but some scenarios may want to use @maxisam's solution until 1.2.0 is released.

like image 44
Anson Avatar answered Sep 27 '22 21:09

Anson