【问题标题】:Angularjs filter negatedAngularjs过滤器被否定
【发布时间】:2012-11-07 21:16:22
【问题描述】:

我有一组项目,我想在 ng-repeat 中过滤,使用 ng-model 作为字符串来过滤集合,到目前为止,我还没有找到一种方法让它在表达式被否定时工作,我正在做这样的事情:

<select ng-model="languageOrigin" ng-change="updatePrice()">
             <option ng-repeat="language in languages">{{language}}</option>
</select>
<select ng-model="languageDestination" ng-change="updatePrice()">
            <option ng-repeat="language in languages | filter:!languageOrigin">{{language}}</option>
</select>

documentation 中,它说我们应该使用 !否定表达式,但仍然没有运气。

我做错了什么?

【问题讨论】:

标签: angularjs


【解决方案1】:

'!'过滤器字符串前面的字符,如下所示:

过滤器:'!'+语言来源

<select ng-model="languageOrigin" ng-change="updatePrice()">
  <option ng-repeat="language in languages">{{language}}</option>
</select>
<select ng-model="languageDestination" ng-change="updatePrice()">
  <option ng-repeat="language in languages | filter:'!'+languageOrigin">{{language}}</option>
</select>

【讨论】:

  • 这就是问题所在。这 '!'必须是人物。谢谢!
  • 在选择时使用ng-options 而不是ng-repeat
  • v1.2.0rc1 还支持这个吗?我无法让它工作。
  • 在 1.2.14 @DavidRivers 中仍受支持
  • 注意:如果过滤器是一个方法,你需要做类似stackoverflow.com/a/17811582/175830
【解决方案2】:

如果使用对象,您可能还对以下内容感兴趣:

<li data-ng-repeat="obj in objs | filter:({obj_attr: '!obj_val'})">
   ...
</li>

在 AngularJS 1.1.5 中测试。

【讨论】:

  • 当 obj_attr 包含字符串值时它可以工作,但我应该如何指定不为空?还是不是''(空)字符串?
  • 这个例子是为我做的,但请注意,如果你想根据不为空的字符串进行过滤,它看起来很糟糕但仍然有效:filter: {prop: '!' } where '!'简单地翻译为“不为空”。丑陋,但它有效:)
【解决方案3】:

更新:见 ENDOH takanao 的回答。

查看 AngularJS source code看起来是 '!'否定谓词的结果,而不是谓词本身

var search = function(obj, text){
    if (text.charAt(0) === '!') {
       return !search(obj, text.substr(1));
    }
    switch (typeof obj) {
    ...

因此,解决此问题的一种方法是 [如果您不喜欢 '!'+myFilter 语法,] 您可以在控制器中定义自己的谓词函数:

$scope.inverseOriginFilter = function(item) {
    return item.search($scope.languageOrigin) == -1
}

然后在你的 HTML 中使用它:

<select ng-model="languageDestination" ng-change="updatePrice()" 
    ng-options="language for language in languages | filter:inverseOriginFilter">
</select>

例如fiddle

【讨论】:

  • 确实有效,但我想知道它是否不应该由AngularJS直接实现......
  • 如果您的每个选择下拉菜单的模型是目标本身,这可以正常工作,但如果它已经附加到其他东西怎么办?
【解决方案4】:

如果您使用的是过滤方法而不是在方法名称前加上“!”不管用。相反,您可以执行以下操作:

// You can register this in your AppCtrl if you like, otherwise just use $scope.
$rootScope.not = function(func) {
    return function (item) { 
        return !func(item); 
    }
};

然后你做:

filter:not(myFilterMethod)

在您的 html 中,它看起来像:

<select ng-model="languageDestination" ng-change="updatePrice()">
  <option ng-repeat="language in languages | filter:not(languageOrigin)">{{language}}</option>
</select>

参考: https://stackoverflow.com/a/17811582/175830

【讨论】:

    【解决方案5】:

    我使用的是 1.3.15 和 ENDOH's 解决方案不起作用。相反,filter:'!':languageOrigin 为我工作。

    【讨论】:

      【解决方案6】:

      为了完全否定 $filter 过滤器,我添加了这个过滤器:

      .filter('$nfilter', ['$filter', function($filter) {
          return function() {
              var itemsToExclude = $filter('filter').apply(null, arguments);
              return arguments[0].filter(x => !itemsToExclude.includes(x));
          }
      }])
      

      在模板中,我们可以这样写:

      <ui-select-choices repeat="type.id as type in data.types | $nfilter:{id: form.typeId}:true | filter: {label: $select.search}">
          <div ng-bind-html="type.label | highlight: $select.search"></div>
      </ui-select-choices>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-11-29
        • 1970-01-01
        • 2014-12-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-29
        相关资源
        最近更新 更多