2013-10-11 4 views
5

Кажется, что это должно быть просто, я просто не могу найти ответ.angularjs - фильтр по нескольким моделям

Скажем, у меня есть массив данных, изложенных как в следующем:

friends = [{name:'John', age:60, location:'Brighton', street:'Middle Street'}, 
{name:'Bob', age:5, location:'Brighton', street:'High Street'}]; 

Теперь я хочу, чтобы фильтровать данные на основе ввода текста, как так:

<input ng-model="searchText"> 
<ul> 
    <li ng-repeat="friend in friends | orderBy:'name' | filter:searchText"> 
    {{friend.name}} - {{friend.location}}</li> 
</ul> 

Этот отлично работает, но он фильтрует входной текст на основе каждого атрибута объекта-друга (имя, возраст, местоположение и улица). Я хотел бы иметь возможность фильтровать только по имени и местоположению (без учета возраста и улицы). Возможно ли это без специального фильтра?

ответ

7

Да, это возможно, просто передавая предикат фильтра вместо строки:

<li ng-repeat="friend in friends | orderBy:'name' | filter:friendContainsSearchText"> 

$scope.friendContainsSearchText = function(friend) { 
    return friend.name.indexOf($scope.searchText) >= 0 || friend.location.indexOf($scope.searchText) >= 0 
} 
+0

Спасибо, работает красиво. Единственное, что стоит упомянуть, это то, что мне нужно было преобразовать текст в нижний регистр и добавить if (! $ Scope.searchText) return 1; чтобы заставить его работать. – user2424495

+0

Просто отметить - добавление 'if (! $ Scope.searchText) return 1;' приведет к возврату всех результатов (без фильтрации), если текст поиска не вводится. Это подкрепление этого подхода в отношении подхода, который я перечисляю, если вам это нужно. – KayakDave

1

В качестве альтернативы вы можете использовать:

<li ng-repeat="friend in friends | orderBy:'name' | filter:{ name :searchText}">

+0

Это, вероятно, то, что вы хотите, за исключением того, что searchText нуждается в кавычках вокруг него. filter: {name: 'searchText'}. Это будет угловато, что это строка, а не выражение. – Adam

+1

На самом деле @Adam проверить эту скрипку: http://jsfiddle.net/Dwesk/1/ Это не работает с кавычками, оборачивается. – KayakDave

+0

Вы абсолютно правы, нам нужно выражение в этом случае, я неправильно понял первоначальный вопрос и ответ. – Adam

2

Вот как мы это делаем с пользовательский фильтр.

ДЕМОНСТРАЦИОННЫЕ: http://plnkr.co/edit/q7tYjOvFjQHSR0QyGETj?p=preview)

[array] | search:query:columns:operator 

> query: this is the term you are looking for 
> columns: an array of the names of the properties you want to look for (if empty, will use the angular filter with query) 
> operator: a boolean to switch between OR (true) and AND (false, default) 

HTML

<ul> 
    <li ng-repeat="item in list | search:query:['name','location']:operator"> 
    <pre>{{item | json}}</pre> 
    </li> 
</ul> 

JS

app.filter('search', function($filter) { 
    return function(input, term, fields, operator) { 
    if (!term) { 
     return input; 
    } 

    fields || (fields = []); 

    if (!fields.length) { 
     return $filter('filter')(input, term); 
    } 

    operator || (operator = false); // true=OR, false=AND 

    var filtered = [], valid; 

    angular.forEach(input, function(value, key) { 
     valid = !operator; 
     for(var i in fields) { 
     var index = value[fields[i]].toLowerCase().indexOf(term.toLowerCase()); 
     // OR : found any? valid 
     if (operator && index >= 0) { 
      valid = true; break; 
     } 
     // AND: not found once? invalid 
     else if (!operator && index < 0) { 
      valid = false; break; 
     } 
     } 
     if (valid) { 
     this.push(value); 
     } 
    }, filtered); 

    return filtered; 
    }; 
}); 
+0

Это отлично работает! – szymon

-1

Вы можете поместить несколько фильтров точно так же, как ....

<div> 
    <input ng-model="Ctrl.firstName" /> 
    <input ng-model="Ctrl.age" /> 

    <li ng-repeat = "employee in Ctrl.employees | filter:{name:Ctrl.firstName} | filter:{age:Ctrl.age}">{{employee.firstName}}</li> 
</div> 
Смежные вопросы