Javascript 在AngularJS中过滤对象映射而不是数组

Javascript 在AngularJS中过滤对象映射而不是数组,javascript,angularjs,Javascript,Angularjs,如果控制器具有$scope属性,而该属性是具有其他属性的对象,而不是像下面这样的数组,我应该如何过滤ng repeat集 下面是一个JSFIDLE: 控制器: function HelloCntl($scope, $filter) { $scope.friends = { john: { name: 'John', phone: '555-1276' }, mary: {

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

下面是一个JSFIDLE:

控制器:

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>

  • {{friend.name}@{{friend.phone}

我想你不能直接用“过滤器”来完成。 查看angular.js中的代码,下面是filter函数的第一行:

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重复:

<li ng-repeat="friend in filteredFriends()">
  • 例如:


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

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

    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;
        };
      });
    
    它只在对象上迭代一次,通过
    name
    phone
    进行比较,可以这样调用

    <li ng-repeat="friend in friends | friendFilter:query">
    
    不要忘记将
    过滤器
    模块插入应用程序

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

    下面是完整的示例:

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

    我有同样的问题,我不能搜索一个对象

    因此,只需返回一个对象,而不是返回一个数组


    希望这对别人有帮助

    除了使用过滤器,您还可以简单地:

    $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>
    
    
    
  • {{user.name}

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

    我的自定义过滤器遍历映射,并为每个元素调用内置过滤器,但鉴于该过滤器只接受一个数组,我将每个元素包装在长度为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个元素的映射,过滤仍然是即时的。

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

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

  • 或者
    ng if
    而不是
    ng hide

    我知道
    过滤器需要数组,但我不知道他们使用数组的
    实例来检查某个东西是否是数组!我本以为会有另一种支票()。无论如何,我把你的例子作为我例子的基础
    
    .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;
      }
    })
    
    <li ng-repeat="(id, friend) in friends | filter:query" ng-hide="id !== query.id">
      <span>{{friend.name}} @ {{friend.phone}}</span>
    </li>