2

How to apply a NOT filter in the following example?

Tried $filter('filter')(users,{ranks: {id: '!' + '15'},true) and $filter('filter')(users, !{ranks: {id:15}},true) but nothing seems to work.

The aim here is to not get user with id = 15 in the filtered array

Controller:

app.controller('MainCtrl', function($scope,$filter) {

  $scope.users = [
    {
      id: 1,
      name: 'John Doe',
      ranks: [ 
        { id: 1, name: 'Admin'},
        { id: 2, name: 'Doe' }
        ],
    },
    {
      id: 2,
      name: 'Barbara Doe',
      ranks: [ { id: 15, name: 'Wife'}, { id: 2, name: 'Doe' }],
    },
    {
      id: 3,
      name: 'Jane Doe',
      ranks: [ { id: 16, name: 'Wife'}, { id: 17, name: 'Doe' }],
    },
  ];

  $scope.filter = $filter('filter')($scope.users, {ranks: {id: !15}},true);


});

HTML:

<p>HTML Filter: List of users without having a rank with id: 15</p>
    <ul>
      <li ng-repeat="user in users | filter:{ranks: {id: '!' + '15'}} : true"> 
        {{ user }}
      </li>
    </ul>

    <p>Controller Filter: List of users without having a rank with id: 15</p>
    <ul>
      <li ng-repeat="user in filter "> 
        {{ user }}
      </li>
    </ul>

Plunker: http://plnkr.co/edit/73lLDpn3uLHozObKn539?p=preview

1
  • @Tushar Tried this $scope.filter = $filter('filter')($scope.users, ranks.id != 15,true); But it is invalid syntax Commented Oct 16, 2015 at 7:05

3 Answers 3

2

You are trying to filter out users where their ranks property contains {id: 15}, you may not have a choice but to write a custom filter, or a predicate function to do that (because this is not a traditional == or != comparison)

Here's an example using a predicate function:

     ranksContainsId15 = function(user, index, users){
        // Look for rank.id === 15
        for(var i=0; i < user.ranks.length; i++){
          if(user.ranks[i].id === 15){
            return false; // so this user will NOT be included
          }
        }

        // no rank.id === 15 found, so this user will be included
        return true;
      }

      $scope.filtered = $filter('filter')($scope.users, ranksContainsId15);

I've updated the example to show all users, then show users that don't have a rank.id == 15 in their ranks array

http://plnkr.co/edit/6x3OEzSiDfIziAnVQ0Em?p=preview

To create predicate functions with a programmable ID, use a function to create them

createPredicateFn = function(id){
    return function(user, index, users){
            for(var i=0; i < user.ranks.length; i++){
              if(user.ranks[i].id === id){
                return false;
              }
            }

            return true;
    }
}

$scope.filtered = $filter('filter')($scope.users, createPredicateFn(15));
Sign up to request clarification or add additional context in comments.

2 Comments

How can I have this predicate function as a global predicate? Custom filter?
@shyamalparikh I think the most natural solution is a custom filter defined in the app module. Otherwise maybe put it into your UserService service? e.g. as UserService.getUsersWithoutRankId(rankId) and use that directly instead of filtering it in the scope. Because putting a filter and/or its predicate function into $scope or $rootScope isn't really a good idea. I think a good controller is a thin controller that delegates other things to a service e.g. I hope this helps!
1

You can create custom filter to filter item manually:

.filter('customFilter', function() {
  return function(array, numberToSkip) {
    var result = [];

    for (i = 0; i < array.length; i++) {
      var arrayItemContainsId = false;

      for (j = 0; j < array[i].ranks.length; j++) {
        if (array[i].ranks[j].id === numberToSkip) {
          arrayItemContainsId = true;
        }
      }

      if (arrayItemContainsId == false) {
        result.push(array[i]);
      }
    }

    return result;
  };
});

and use this like this:

<ul>
   <li ng-repeat="user in users | customFilter: 15"> 
      {{ user }}
   </li>
</ul>

2 Comments

Well that is an alternative but angularjs has an option of NOT filtering then why not use it? Check this: docs.angularjs.org/api/ng/filter/filter Also check stackoverflow.com/questions/22666366/…
@shyamalparikh Most likely because you are testing for a container having a given element, as opposed to being equal / not equal to something, and what you're doing is making ng test user.ranks (which is a list) against an object ({id: 15}), which isn't what you want. A custom filter like Dawid, or a custom predicate function like in my answer is way to implement this
-1

You have implemented the not filter slightly wrong. Use this instead

<li ng-repeat="user in users | filter: !{ranks: {id:15}} : true">

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.