【问题标题】:Angularjs: How to apply NOT filter?Angularjs:如何应用 NOT 过滤器?
【发布时间】:2016-01-14 20:16:18
【问题描述】:

如何在以下示例中应用 NOT 过滤器?

尝试了$filter('filter')(users,{ranks: {id: '!' + '15'},true)$filter('filter')(users, !{ranks: {id:15}},true),但似乎没有任何效果。

这里的目的是在过滤后的数组中不获取 id = 15 的用户

控制器:

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

【问题讨论】:

  • @Tushar 试过这个 $scope.filter = $filter('filter')($scope.users,ranks.id != 15,true);但它是无效的语法

标签: javascript angularjs filter angular-filters


【解决方案1】:

您正试图过滤掉排名属性包含 {id: 15} 的用户,您可能别无选择,只能编写自定义过滤器或谓词函数来执行此操作(因为这不是传统的 ==或 != 比较)

下面是一个使用谓词函数的例子:

     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);

我更新了示例以显示所有用户,然后显示排名数组中没有 rank.id == 15 的用户

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

要创建具有可编程 ID 的谓词函数,请使用函数来创建它们

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));

【讨论】:

  • 我怎样才能将这个谓词函数用作全局谓词?自定义过滤器?
  • @syamalparikh 我认为最自然的解决方案是在 app 模块中定义的自定义过滤器。否则可能将其放入您的 UserService 服务中?例如作为 UserService.getUsersWithoutRankId(rankId) 并直接使用它而不是在范围内过滤它。因为将过滤器和/或其谓词函数放入 $scope 或 $rootScope 并不是一个好主意。我认为一个好的控制器是一个 thin 控制器,它将其他事情委托给服务,例如我希望这会有所帮助!
【解决方案2】:

您可以创建自定义过滤器来手动过滤项目:

.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;
  };
});

并像这样使用它:

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

【讨论】:

  • 嗯,这是一个替代方案,但 angularjs 有一个不过滤的选项,那么为什么不使用它呢?检查这个:docs.angularjs.org/api/ng/filter/filter 还要检查stackoverflow.com/questions/22666366/…
  • @syamalparikh 很可能是因为您正在测试具有给定元素的容器,而不是 equal / notequal 某物,并且您正在做的是针对对象({id:15})进行ng test user.ranks(这是一个列表),这不是您想要的。像 Dawid 这样的自定义过滤器,或者像我的回答中这样的自定义谓词函数是实现这一点的方法
【解决方案3】:

您实现的 not 过滤器略有错误。改用这个

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-09
    • 1970-01-01
    • 2012-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多