过滤对象贴图而不是AngularJS中的数组

时间:2012-12-14 23:09:11

标签: javascript angularjs

如果控制器具有$ scope属性,该属性是具有其他属性的对象而不是下面的数组,我应该如何过滤ng-repeat集?

这是一个JSFiddle:http://jsfiddle.net/ZfGx4/110/

控制器:

function HelloCntl($scope, $filter) {
    $scope.friends = {
        john: {
            name: 'John',
            phone: '555-1276'
        },
        mary: {
            name: 'Mary',
            phone: '800-BIG-MARY'
        },
        mike: {
            name: 'Mike',
            phone: '555-4321'
        },
        adam: {
            name: 'Adam',
            phone: '555-5678'
        },
        julie: {
            name: 'Julie',
            phone: '555-8765'
        }
    };
}​

模板:

<div ng:app>
 <div ng-controller="HelloCntl">
  <input placeholder="Type to filter" ng-model="query">     
  <ul>
   <li ng-repeat="(id, friend) in friends | filter:query">
    <span>{{friend.name}} @ {{friend.phone}}</span>
   </li>
  </ul>
 </div>
</div>

6 个答案:

答案 0 :(得分:26)

我会将数据结构更改为数组。无论如何,这是另一个过滤你的朋友对象的实现。

angular.module('filters',['utils'])
  .filter('friendFilter', function(utils){

    return function(input, query){
      if(!query) return input;
      var result = [];

      angular.forEach(input, function(friend){
        if(utils.compareStr(friend.name, query) ||
           utils.compareStr(friend.phone, query))
          result.push(friend);          
      });
      return result;
    };
  });

这只对对象进行一次迭代,按namephone进行比较,可以这样调用。

<li ng-repeat="friend in friends | friendFilter:query">

我在另一个模块中定义了compareStr,但你真的不需要这样做。

angular.module('utils', [])
  .factory('utils', function(){
    return{
      compareStr: function(stra, strb){
        stra = ("" + stra).toLowerCase();
        strb = ("" + strb).toLowerCase();
        return stra.indexOf(strb) !== -1;
      }
    };
  });

不要忘记将filters模块注入您的应用

angular.module('app',['filters'])

以下是完整示例:http://jsbin.com/acagag/5/edit

答案 1 :(得分:13)

我猜你不能直接用'过滤器'来做。 查看angular.js中的代码,这些是过滤函数的第一行:

function filterFilter() {
  return function(array, expression) {
    if (!(array instanceof Array)) return array;

因此,如果它收到与数组不同的内容,它什么都不做。

这是一种方法,不确定我是否会推荐它,但这是一个想法:

在控制器中,只需在将数组传递给过滤器之前转换为数组:

$scope.filteredFriends = function() {
    var array = [];
    for(key in $scope.friends) {
        array.push($scope.friends[key]);
    }
    return $filter('filter')(array, $scope.query);
}

和ng-repeat:

<li ng-repeat="friend in filteredFriends()">

示例:http://jsbin.com/acagag/2/edit

也许更好的解决方案是编写自定义过滤器。

答案 2 :(得分:3)

我遇到了同样的问题,并成功创建了我自己的接受地图的过滤器,同时仍然使用内置过滤器进行实际匹配。

我的自定义过滤器遍历地图,并且对于每个元素调用内置过滤器,但是假设该过滤器只接受一个数组,我将每个元素包装在长度为1的数组中(下面的[data])。因此,如果输出数组的长度仍为1,则匹配成功。

.filter('mapFilter', function($filter) {
  var filter = $filter('filter');

  return function(map, expression, comparator) {
    if (! expression) return map;

    var result = {};
    angular.forEach(map, function(data, index) {
      if (filter([data], expression, comparator).length)
        result[index] = data;          
    });

    return result;
  }
})

这种设置当然会失去效率,因为内置过滤器需要确定它需要为地图中的每个元素做什么,而不是只有一次如果给它一个包含所有元素的数组,但在我的情况下,使用500个元素的地图,过滤仍然很不稳定。

答案 3 :(得分:1)

我举例说明了如何不将对象更改为数组。我认为这回答了更正确的问题。

我有同样的问题,我无法搜索对象。

http://jsbin.com/acagag/223/edit

angular.module('filters',['utils'])
  .filter('friendFilter', function(utils){

    return function(input, query){
      if(!query) return input;
      var result = {};

      angular.forEach(input, function(friendData, friend){
        if(utils.compareStr(friend, query) ||
           utils.compareStr(friendData.phone, query))
          result[friend] = friendData;          
      });
      return result;
    };
  });

所以只需返回一个对象而不是返回一个数组。

希望这有助于某人!

答案 4 :(得分:1)

不是最佳解决方案,但如果你想要快速和肮脏的东西:

<li ng-repeat="(id, friend) in friends | filter:query" ng-hide="id !== query.id">
  <span>{{friend.name}} @ {{friend.phone}}</span>
</li>

ng-if代替ng-hide

答案 5 :(得分:0)

您可以简单地使用过滤器,而不是使用过滤器:

$http.get('api/users').success(function(data){
    angular.forEach(data, function(value, key){
        users.push(value);
    });
    $scope.users = users;
});

在模板中

<input type="text" ng-model="query" placeholder="Search user"/>

<li ng-repeat="user in users | filter:query">
    {{ user.name }}
</li>