Reputation: 30195
I have a simple ng-repeat like that:
<input type="text" ng-model="vm.filter">
<div ng-repeat="tenant in vm.tenants | filter : vm.filter : vm.contains">
</div>
Now I want to filter tenants based on the value of the filter, e.g. to find if a name of a tenant contains the filter expression like that
function contains(actual, expected) {
return actual.name.indexOf(expected) >= 0;
}
What I do not understand is why I get a tenant.name
in the contains function instead of the tenant
itself. I know for a simple case I can do something like filter | {name: vm.filter} | vm.contains
, but what if I want to do filtering based on multiple properties (e.g. name, phone, etc.)
Upvotes: 1
Views: 1407
Reputation: 41065
What I do not understand is why I get a tenant.name in the contains function instead of the tenant itself.
What's happening is that angular is providing the comparator all levels of the object in an attempt to do a deep filtering i.e. it attempts to match your filter to all hierarchy levels in the object. If you console.log all the values, you'll see that you get the full object too (after all the properties).
One way to make this work would be something like
...
<div ng-repeat="tenant in vm.tenants | filter : vm.contains(vm.filter)">
...
and then
...
contains: function(filter) {
return function(tenant) {
return tenant.name.indexOf(filter) !== -1;
}
}
...
Fiddle - https://jsfiddle.net/81384sd7/
Upvotes: 1
Reputation: 942
You can use an object to store the filters you want to apply. For example:
$scope.filterBy = {
name: "Bob",
phone: "07"
};
Then configure fields to edit the filters:
<input type="text" ng-model="filterBy.name" />
<input type="text" ng-model="filterBy.phone" />
Then just filter by this object.
<div ng-repeat="tenant in vm.tenants | filter : filterBy">
Take a look at my previous answer which is very similar except also allows selections to be made before a filter being applied manually with a button:
Applying a angularjs filter after "Apply" button click
I hope this helps.
Upvotes: 1
Reputation: 62743
You'll want to test for the presence of both those conditions and return the value if both are present. Something like this:
function contains(actual, expected) {
if (actual.name.indexOf(expected) >= 0 && actual.phone.indexOf(expected) >= 0) {
return actual;
}
}
Upvotes: 0