对ngRepeat中的对象数组进行Angularjs过滤不会还原具有空搜索属性的项目

时间:2014-02-04 08:50:42

标签: javascript angularjs angularjs-ng-repeat

请考虑以下示例:

模板:

<body  ng-controller="MainCtrl">
Search: <input ng-model="search.$" ><br>
Search by tag: <input ng-model="search.tag" >
    <p ng-repeat="item in items | filter:search">
        <span>{{item.content}}</span> <span>{{item.tag}}</span>
    </p>
</body>

脚本:

 app.controller('MainCtrl',  function ($scope, $filter, filterFilter) {
 $scope.items = [
     {content:'3333113', tag:['a','b','c']},
     {content:'111111g', tag:['b','c','d']},
     {content:'345345', tag:[]},
     {content:'2221122', tag:['c','d','e']},
     {content:'2221122', tag:[]},
     {content:'333', tag:[]}
  ];
});

使用任何数据通过第一个输入ng-model="search.$"进行搜索时,一切正常。 当通过seond输入ng-model="search.tag"进行搜索时,搜索确实可以通过ab之类的标签进行搜索,但是当它被清除时,恢复的数组缺少具有空搜索值的项目,例如在此示例中为{content:'2221122', tag:[]}

jsBin example

为什么会这样?有没有一种简单的方法可以避免它?

3 个答案:

答案 0 :(得分:3)

简答:

这是一个有效的代码:http://jsbin.com/AwunOyAt/2

如果search.tag为空,则需要一个指令使其未定义:

<强>指令:

app.directive('modelUndefined', function(){
  return {
    require: 'ngModel',
    link: function(scope,elm,attrs,ngModel){
      ngModel.$parsers.push(function(val){             
         return val === "" ? undefined : val;
      });
    }
  }
});

<强> HTML:

<input ng-model="search.tag" model-undefined>

答案很长:

来自filter:filter的文档:

  

在HTML模板绑定中

     

{{filter_expression | filter:expression:comparator}}

     

<强>参数#表达​​

     

对象:模式对象可用于过滤数组包含的对象的特定属性。例如{name:“M”,phone:“1”}谓词将返回一个项目数组,其属性名称包含“M”,属性手机包含“1”。可以使用特殊属性名称$(如{$:“text”})来接受对象的任何属性的匹配。这相当于如上所述与字符串匹配的简单子字符串。

如您所见,过滤器表达式可以是具有多个谓词的对象

如何追踪它?

最初ngModel在输入之前不会设置search.tag,因此它仍未定义。

首先我将输入传递给search.$,搜索对象如下:

$scope.search = {
  '$' : 'something'
}

然后我会将一些内容传递给搜索对象search.tag

$scope.search = {
  '$' : 'something',
  'tag': 'anything'
}

但是当我清除它时,搜索对象仍然具有tag属性

$scope.search = {
  '$' : 'something',
  'tag': ''
}
基于这两个谓词的

filter:filter个过滤器,这是source code

  case "object":
    // jshint +W086
    for (var key in expression) {
      (function(path) {
        if (typeof expression[path] == 'undefined') return;
        predicates.push(function(value) {
          return search(path == '$' ? value : (value && value[path]), expression[path]);
        });
      })(key);
  • 在我们的例子中,表达式为search object,路径为$tag
  • 请参阅此行:if (typeof expression[path] == 'undefined') return;
  • 如果我们设置search.tag = undefined,则过滤器会忽略它。
  • 但如果我们设置search.tag = '',则tag路径会添加到谓词检查数组中。

如何强制ngModel使search.tag在空的时候未定义?

请参阅上面的指令,您需要使用ngModelController#$parsers来更改视图值在更新模型时的转换方式。

答案 1 :(得分:1)

我不知道是否有帮助,但我提出以下内容:

<p>{{search.tag == undefined}}</p>

然后显示它最初是undefined,稍后它是一个空字符串(如果你清空输入)。然后搜索结果才有意义。

答案 2 :(得分:0)

看起来AngularJS版本1.2.10有变化。使用https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.min.js不会消除空条目。