Sobis
Sobis

Reputation: 1405

Filter not working in ng-repeat

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

Answers (3)

TOBlender
TOBlender

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

Jay Shukla
Jay Shukla

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

Yoshi
Yoshi

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

Related Questions