Reputation: 1405
I have a question about filtering in ng-repeat.
Here is template code:
<li ng-repeat="friend in friends | filter:personFilter">
<span>{{friend.name}}</span>
<span>{{friend.phone}}</span>
<span>{{friend.items | GetItemsTitels}}</span>
</li>
</lang-html>
where GetItemsTitels return some string. Here is live demo
Why doenst personFilter working on last column which shows stirng returned from GetItemsTitels filter? If jsfiddle if you type 'aa' in filter your don't get any result. Is it because filter for this column is already assigned and that is why personFilter doesn't apply for it?
Upvotes: 4
Views: 14243
Reputation: 1063
From what I understand:
Filters only work on "array" type, not "object" type.
given:
var friends={'a':'april','b':'bob'};
<li ng-repeat="friend in friends | filter:personFilter">
<!-- personFilter will not run -->
var friends=[{code:'a',name:'april'},{code:'b',name:'bob'}];
personFilter=function(item){
return item.code !== personModel
}
<li ng-repeat="friend in friends | filter:personFilter">
<!-- will filter -->
Upvotes: 6
Reputation: 5826
if you type 'aa' in filter your don't get any result because it will filter this 'aa' in friends list where 'aa' is not exists. As there are ids in items array which will again filters and returns string from all items. So whatever you type in text box will be filter from friends list only. If you still want to achieve this same thing then you have to modify you friends JSON.
<li ng-repeat="friend in friends | filter:personFilter">
<span>{{friend.name}}</span>
<span>{{friend.phone}}</span>
<span>{{friend.items | GetItemsTitels}}</span>
</li>
Here it is http://jsfiddle.net/RXmpT/3/
Upvotes: 1
Reputation: 54649
A filter on ng-repeat
will only take into account what is in the object. Not what might be displayed while the loop is running. You could however populate friends
with the real data and then the filter should work.
Usage:
<ul>
<li ng-repeat="friend in friends | injectItemTitles:'itemTitles' | filter:personFilter">
<span>{{friend.name}}</span>
<span>{{friend.phone}}</span>
<span>{{friend.itemTitles.join(', ')}}</span>
</li>
</ul>
Demo: http://jsbin.com/iciyoq/2/
There might be one problem with this approach, as it whould inject the item titels on each digest cycle. So it could be better to apply the injectItemTitles
-filter in the controller on large datasets.
Full code:
(function (app, ng) {
'use strict';
app.controller('MainCtrl', ['$scope', function($scope) {
$scope.friends = [{
name: 'John',
phone: '555-1276',
items : ['id0', 'id1']
}, {
name: 'Mary',
phone: '800-BIG-MARY',
items : ['id1', 'id2']
}, {
name: 'Mike',
phone: '555-4321',
items : ['id2', 'id3']
}, {
name: 'Adam',
phone: '555-5678',
items : ['id3', 'id4']
}, {
name: 'Julie',
phone: '555-8765',
items : ['id4', 'id5']
}];
}]);
app.filter('injectItemTitles', ['AllItems', 'getItemTitlesFilter', function(AllItems, getItemTitlesFilter) {
return function(friends, prop){
return friends.map(function(friend) {
friend[prop] = getItemTitlesFilter(friend.items);
return friend;
});
};
}]);
app.filter('getItemTitles', ['AllItems', function(AllItems){
return function(items){
return items.map(function (id) {
return AllItems[id];
});
};
}]);
app.service('AllItems', function(){
return {
'id0' : 'aaa',
'id1' : 'aab',
'id2' : 'aba',
'id3' : 'abb',
'id4' : 'baa',
'id5' : 'bab',
'id6' : 'bba',
'id7' : 'bbb'
};
});
}(angular.module('app', []), angular));
Upvotes: 2