Angular中ng-repeat如何跳过匹配表达式的项

94

我正在寻找一种方法,基本上是告诉Angular,如果一个ng-repeat中的项符合某个表达式,跳过它,就像使用continue一样。

在控制器中:

$scope.players = [{
    name_key:'FirstPerson', first_name:'First', last_name:'Person'
}, {
    name_key:'SecondPerson', first_name:'Second', last_name:'Person'
}]

现在我想在我的模板中展示所有不匹配name_key='FirstPerson'的人。我认为这必须是筛选器,所以我设置了一个 Plunkr 来尝试解决它,但是没有任何运气。Plunkr 尝试


我试图理解:你是想展示所有的项目,但标出哪些匹配和哪些不匹配?还是只是进行筛选? - Maxim Shoustin
3个回答

144

正如@Maxim Shoustin所建议的那样,实现您想要的最好方法是使用自定义过滤器。
但还有其他方法,其中一种是在与ng-repeat指令相同的元素上使用ng-if指令(此外,这里是plunker):

<ul>
    <li ng-repeat="player in players" ng-if="player.name_key!='FirstPerson'"></li>
</ul>

从美学角度来看,这可能会有一些小的不利之处,但是它有一个重要优势,即您的过滤可以基于规则而不是紧密耦合到players数组,并且可以轻松访问应用程序范围内的其他数据:

  <li 
      ng-repeat="player in players" 
      ng-if="app.loggedIn && player.name != user.name"
  ></li>

更新
如前所述,这是解决此类问题的其中一种方案,可能适合也可能不适合您的需求。
正如评论中指出的,ng-if是一个指令,这实际上意味着它可能会在后台执行比您预期更多的操作。
例如,ng-if 从其父级创建一个新范围

在 ngIf 中创建的作用域使用原型继承来自其父作用域。

通常,这不会影响正常行为,但为了防止意外情况,请在实施之前牢记这一点。


这正是我一直在寻找的,我知道必须有某种简单明了的方法来完成它,而不需要使用自定义过滤器。谢谢! - aron.duby
注意:ng-if 的某些作用域行为可能会很棘手。我尝试过这种方法,但它在其他地方引起了问题。特别是,我有一个“监视器”指令,在重复器完成时广播事件。在将 ng-if 添加到此重复器后,它不再触发该事件。自定义过滤器实际上可能是最干净的方法。 - claywhipkey
@claywhipkey 你说得没错,最干净的方法是使用过滤器,但并不适用于所有情况。不管怎样,感谢您的评论,并且您可以看到我已经在答案中添加了一个 heads up 更新,以让任何人都意识到使用指令来过滤数据的影响。 - gion_13

45

我知道这是一个旧问题,但如果有人在寻找另一种可能的解决方案,这里是另一种解决方法 - 使用标准筛选器功能:

对象: 可以使用模式对象来过滤数组中包含的对象的特定属性。例如 {name:"M", phone:"1"} 谓词将返回一个包含属性 name 包含 "M" 和属性 phone 包含 "1" 的项的数组。... 可以通过在字符串前加 ! 来否定谓词。 例如 {name: "!M"} 谓词将返回一个具有不包含 "M" 的属性名的项的数组。

因此,对于 TS 示例,应该使用类似以下方式:

<ul>
    <li ng-repeat="player in players | filter: { name_key: '!FirstPerson' }"></li>
</ul>

无需编写自定义过滤器,也不需要使用带有新作用域的 ng-if


没有创建自定义过滤器或新作用域,正如作者所述。非常适合在列表中跳过单个值。 - mbokil
我认为你需要从'player.name_key'中省略'player' - 因此在上面的示例中它将只是"{name_key:'!FirstPerson'}"。 - smithml
我从来没有成功地让Angular与空键协调工作。有没有什么技巧可以使用内置过滤器来实现player in players | filter: { name_key: '' }的等效操作?那个特定的指令不会匹配只有没有/空name_key的球员。相反,name_key:'!'旨在选择任何具有非空name_key的球员也不起作用。 - Eric L.
你可以查看这个答案。 - Ilya Luzyanin
4
请注意,此方法仅适用于数组,而不适用于对象属性,例如ng-repeat="(key, val) in player"中的情况。 - David Diez

19
你可以在实现 ng-repeat 时使用自定义过滤器,例如:

你可以这样使用自定义过滤器:

 data-ng-repeat="player in players |  myfilter:search.name

myfilter.js:

app.filter('myfilter', function() {


   return function( items, name) {
    var filtered = [];

    angular.forEach(items, function(item) {

      if(name == undefined || name == ''){
        filtered.push(item);
        }

      /* only if you want start With*/
      // else if(item.name_key.substring(0, name.length) !== name){
      //   filtered.push(item);
      // }

      /* if you want contains*/
      // else if(item.name_key.indexOf(name) < 0 ){
      //   filtered.push(item);
      // }

       /* if you want match full name*/
       else if(item.name_key !== name ){
        filtered.push(item);
      }
    });

    return filtered;
  };
});

演示 Plunker


感谢您为此付出的努力。它肯定是正确的,但最终我还是选择了@gion_13在代码中提供的方便,所以我想最好将他的答案标记为采纳答案。 - aron.duby

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接