Reputation: 13962
I've got a text box in my html and I would like to filter the results on my page by a logical AND of the terms I type in the box. Let me demonstrate
Suppose on my page I've got
- Example number 1
- Example number 2
- Example number 3
Normally, if I want to filter the results I'll do something like
<input type= "text" ng-model= "query">
And later
<tr ng-repeat= "thing in blah | filter : query">
<td> {{thing}} </td>
</tr>
So if I typed in
"Example"
I would understandably not "filter" anything. However, how would I do a logical AND, with multiple search terms? For example, if I type in
"Example 1"
I should get back only the first example, because it contains both "Example" AND "1". I've not seen anything in the angular documentation that would allow me to do this, but I'm sure it can be done by creating my own filter, I just don't have any experience in doing something like this.
Upvotes: 4
Views: 2194
Reputation: 5870
My solution. It takes advantage of Angulars filterFilter and has 3 advantages over the chosen answer:
Here is the code:
app.filter('multiple', ['filterFilter', function (filterFilter) {
return function (items, query) {
if (!query) return items;
var terms = query.split(/\s+/);
var result = items;
terms.forEach(function (term) {
result = filterFilter(result,term);
});
return result;
}
}]);
Upvotes: 2
Reputation: 4605
The accepted answer by Marc helped me as well, however, when using objects rather than strings you need to use dot notation to access the specific values. (for example 'name' and 'title')
items.forEach(function(item){ // iterate through array of items
var passTest = true;
var found = false;
terms.forEach(function(term){ // iterate through terms found in query box
// if any terms aren't found, passTest is set to and remains false
found = (item.name.toLowerCase().indexOf(term.toLowerCase()) > -1)
|| (item.title.toLowerCase().indexOf(term.toLowerCase()) > -1);
passTest = passTest && found;
});
// Add item to return array only if passTest is true -- all search terms were found in item
if (passTest) { arrayToReturn.push(item); }
});
Upvotes: 0
Reputation: 9409
Create a custom filter:
filter('and', function($log) {
return function(items, query) {
if (!query) return items; // return all items if nothing in query box
var terms = query.split(' '); //split query terms by space character
var arrayToReturn = [];
items.forEach(function(item){ // iterate through array of items
var passTest = true;
terms.forEach(function(term){ // iterate through terms found in query box
// if any terms aren't found, passTest is set to and remains false
passTest = passTest && (item.toLowerCase().indexOf(term.toLowerCase()) > -1);
});
// Add item to return array only if passTest is true -- all search terms were found in item
if (passTest) { arrayToReturn.push(item); }
});
return arrayToReturn;
}
})
and use it in place of filter: query
:
<tr ng-repeat="thing in blah | and:query">
Upvotes: 4