2012-12-14 73 views
24

給定一個具有$ scope屬性的控制器,該屬性是具有其他屬性而不是像下面這樣的數組的對象,應如何過濾ng-repeat集?在AngularJS上的對象映射而不是陣列上過濾

這裏是一個的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> 
+2

的jsfiddle不再起作用 – Jackie

回答

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

+0

偉大的解決方案,謝謝! –

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

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

實施例:http://jsbin.com/acagag/2/edit

也許更好的解決方案是編寫一個自定義過濾器。

+0

我知道'filter'濾波器所需的陣列,但我沒有不知道他們使用'instanceof Array'來檢查是否有數組!我會期待一種不同的支票(http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/)。無論如何,我把你的榜樣作爲我的榜樣的基礎。 – jaime

+0

+1爲什麼說!謝謝。 – JnBrymn

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; 
    }; 
    }); 

所以才而不是返回一個數組返回一個對象。

希望這可以幫助別人!

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> 
3

我有同樣的問題,並通過創建我自己的過濾器,它接受一個地圖得手,同時仍然使用內置過濾器進行實際匹配。我的自定義過濾器遍歷映射,併爲每個元素調用內置的過濾器,但鑑於該過濾器只接受一個數組,我將每個元素包裝在一個長度爲1的數組中(下面的[數據])。所以匹配成功,如果輸出數組的長度仍然是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個元素的地圖過濾仍然instanteanous。

+0

這很好。謝謝 –

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