如果控制器具有$ 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>
答案 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;
};
});
这只对对象进行一次迭代,按name
和phone
进行比较,可以这样调用。
<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>