Фильтрация с помощью нескольких конкретных свойств модели в AngularJS (в отношении OR)
Посмотрите на пример здесь: http://docs.angularjs.org/api/ng.filter:filter
Вы можете выполнить поиск по любому из свойств телефона с помощью <input ng-model="search">
а поиск по просто имени - <input ng-model="search.name">
, и результаты соответствующим образом отфильтрованы. по имени (ввод номера телефона не дает никаких результатов, как ожидалось).
Пусть говорят, у меня есть модель со свойством "имя", свойство "телефон", и "секретно" собственности, как бы я идти о фильтрации со стороны как "имя" и "телефон" свойства, и не "секрет" собственность? Таким образом, по сути, пользователь может ввести имя или номер телефона, и ng-repeat
будет фильтровать правильно, но даже если пользователь введет значение, равное части "секретного" значения, он ничего не вернет.
Благодарю.
Ответы
Ответ 1
Вот plunker
Новый плункер с чистым кодом и где оба элемента запроса и списка поиска нечувствительны к регистру
Основная идея - создать функцию фильтрации для достижения этой цели.
От официальный документ
Функция : функция предиката может использоваться для записи произвольных фильтров. Функция вызывается для каждого элемента массива. Конечным результатом является массив из тех элементов, которые предикат возвратил true для.
<input ng-model="query">
<tr ng-repeat="smartphone in smartphones | filter: search ">
$scope.search = function(item) {
if (!$scope.query || (item.brand.toLowerCase().indexOf($scope.query) != -1) || (item.model.toLowerCase().indexOf($scope.query.toLowerCase()) != -1) ){
return true;
}
return false;
};
Обновление
Некоторые люди могут беспокоиться о производительности в реальном мире, что верно.
В реальном мире мы, вероятно, сделаем этот вид фильтра с контроллера.
Вот деталь post, показывающий, как это сделать.
мы добавим ng-change
для ввода новых изменений поиска
а затем запустить функцию фильтра.
Ответ 2
Вы можете передать объект в качестве параметра в выражение фильтра, как описано в Справочном руководстве по API. Этот объект может выборочно применять интересующие вас свойства, например:
<input ng-model="search.name">
<input ng-model="search.phone">
<input ng-model="search.secret">
<tr ng-repeat="user in users | filter:{name: search.name, phone: search.phone}">
Здесь Plunker
Heads up... этот пример отлично работает с AngularJS 1.1.5, но не всегда в 1.0.7. В этом примере 1.0.7 будет инициализироваться всем отфильтрованным, а затем работать, когда вы начнете использовать входы. Он ведет себя так же, как входы имеют несогласованные значения в них, хотя они начинаются с пустого. Если вы хотите оставаться на стабильных выпусках, продолжайте и попробуйте это для своей ситуации, но некоторые сценарии могут захотеть использовать решение @maxisam до выпуска 1.2.0.
Ответ 3
Я вдохновил себя на ответ @maxisam и создал свою собственную функцию сортировки, и я бы поделился ею (потому что мне скучно).
Ситуация
Я хочу фильтровать через массив автомобилей. Выбранные свойства для фильтрации - это имя, год, цена и км. Цена собственности и км - это номера (следовательно, использование .toString
). Я также хочу контролировать заглавные буквы (отсюда .toLowerCase
). Также я хочу, чтобы иметь возможность разделить мой запрос фильтра на разные слова (например, с учетом фильтра 2006 Acura, он находит совпадения с 2006 годом и Acura с именем).
Функция я переходит к фильтру
var attrs = [car.name.toLowerCase(), car.year, car.price.toString(), car.km.toString()],
filters = $scope.tableOpts.filter.toLowerCase().split(' '),
isStringInArray = function (string, array){
for (var j=0;j<array.length;j++){
if (array[j].indexOf(string)!==-1){return true;}
}
return false;
};
for (var i=0;i<filters.length;i++){
if (!isStringInArray(filters[i], attrs)){return false;}
}
return true;
};
Ответ 4
Если вы открыты для использования сторонних библиотек, "Angular Filters" с хорошим набором фильтров могут быть полезны:
https://github.com/a8m/angular-filter#filterby
collection | filterBy: [prop, nested.prop, etc..]: search
Ответ 5
Надеюсь, что этот ответ поможет, Множественный фильтр значений
И рабочий пример в этом fiddle
arrayOfObjectswithKeys | filterMultiple:{key1:['value1','value2','value3',...etc],key2:'value4',key3:[value5,value6,...etc]}
Ответ 6
Здесь есть множество хороших решений, но я бы предложил пойти на другой маршрут с этим. Если поиск является самым важным, и секретное свойство вообще не используется в представлении; мой подход для этого заключается в использовании встроенного фильтра angular со всеми его преимуществами и просто сопоставления модели с новым массивом объектов.
Пример из вопроса:
$scope.people = members.map(function(member) {
return {
name: member.name,
phone: member.phone
}});
Теперь в html просто используйте регулярный фильтр для поиска обоих этих свойств.
<div ng-repeat="member in people | filter: searchString">
Ответ 7
http://plnkr.co/edit/A2IG03FLYnEYMpZ5RxEm?p=preview
Вот чувствительный к регистру поиск, который также отделяет ваш поиск от слов для поиска в каждой модели. Только когда он найдет пробел, он попытается разбить запрос на массив и затем выполнить поиск каждого слова.
Он возвращает значение true, если каждое слово находится хотя бы в одной из моделей.
$scope.songSearch = function (row) {
var query = angular.lowercase($scope.query);
if (query.indexOf(" ") > 0) {
query_array = query.split(" ");
search_result = false;
for (x in query_array) {
query = query_array[x];
if (angular.lowercase(row.model1).indexOf(query || '') !== -1 || angular.lowercase(row.model2).indexOf(query || '') !== -1 || angular.lowercase(row.model3).indexOf(query || '') !== -1){
search_result = true;
} else {
search_result = false;
break;
}
}
return search_result;
} else {
return (angular.lowercase(row.model1).indexOf(query || '') !== -1 || angular.lowercase(row.model2).indexOf(query || '') !== -1 || angular.lowercase(row.model3).indexOf(query || '') !== -1);
}
};
Ответ 8
Довольно прямой подход с использованием filterBy в angularJs
Для работы plnkr выполните следующую ссылку
http://plnkr.co/edit/US6xE4h0gD5CEYV0aMDf?p=preview
Это специально использовало одно свойство для поиска по нескольким столбцам, но не для всех.
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<script data-require="[email protected]" data-semver="1.4.1" src="https://code.angularjs.org/1.4.1/angular.js"></script>
<script data-require="[email protected]" data-semver="0.5.2" src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.2/angular-filter.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="myCtrl as vm">
<input type="text" placeholder="enter your search text" ng-model="vm.searchText" />
<table>
<tr ng-repeat="row in vm.tableData | filterBy: ['col1','col2']: vm.searchText">
<td>{{row.col1}}</td>
<td>{{row.col2}}</td>
<td>{{row.col3}}</td>
</tr>
</table>
<p>This will show filter from <b>two columns</b> only(col1 and col2) . Not from all. Whatever columns you add into filter array they
will be searched. all columns will be used by default if you use <b>filter: vm.searchText</b></p>
</body>
</html>
контроллер
// Code goes here
(function(){
var myApp = angular.module('myApp',['angular.filter']);
myApp.controller('myCtrl', function($scope){
var vm= this;
vm.x = 20;
vm.tableData = [
{
col1: 'Ashok',
col2: 'Tewatia',
col3: '12'
},{
col1: 'Babita',
col2: 'Malik',
col3: '34'
},{
col1: 'Dinesh',
col2: 'Tewatia',
col3: '56'
},{
col1: 'Sabita',
col2: 'Malik',
col3: '78'
}
];
})
})();
Ответ 9
Здесь простое решение для тех, кто хочет быстрый фильтр против объекта:
<select>
<option ng-repeat="card in deck.Cards | filter: {Type: 'Face'}">{{card.Name}}</option>
</select>
Фильтр массива позволяет вам имитировать объект, который вы пытаетесь фильтровать. В приведенном выше случае следующие классы будут работать нормально:
var card = function(name, type) {
var _name = name;
var _type = type;
return {
Name: _name,
Type: _type
};
};
И где колода может выглядеть так:
var deck = function() {
var _cards = [new card('Jack', 'Face'),
new card('7', 'Numeral')];
return {
Cards: _cards
};
};
И если вы хотите отфильтровать несколько свойств объекта, просто разделите имена полей запятой:
<select>
<option ng-repeat="card in deck.Cards | filter: {Type: 'Face', Name: 'Jack'}">{{card.Name}}</option>
</select>
EDIT:
Здесь работает plnkr, который предоставляет пример одиночных и множественных фильтров свойств:
http://embed.plnkr.co/i0wCx6l1WPYljk57SXzV/
Ответ 10
Мне нравится держать, когда это возможно. Мне нужно было группировать International, фильтровать по всем столбцам, отображать счетчик для каждой группы и скрывать группу, если не было элементов.
Плюс я не хотел добавлять настраиваемый фильтр только для чего-то простого.
<tbody>
<tr ng-show="fusa.length > 0"><td colspan="8"><h3>USA ({{fusa.length}})</h3></td></tr>
<tr ng-repeat="t in fusa = (usa = (vm.assignmentLookups | filter: {isInternational: false}) | filter: vm.searchResultText)">
<td>{{$index + 1}}</td>
<td ng-bind-html="vm.highlight(t.title, vm.searchResultText)"></td>
<td ng-bind-html="vm.highlight(t.genericName, vm.searchResultText)"></td>
<td ng-bind-html="vm.highlight(t.mechanismsOfAction, vm.searchResultText)"></td>
<td ng-bind-html="vm.highlight(t.diseaseStateIndication, vm.searchResultText)"></td>
<td ng-bind-html="vm.highlight(t.assignedTo, vm.searchResultText)"></td>
<td ng-bind-html="t.lastPublished | date:'medium'"></td>
</tr>
</tbody>
<tbody>
<tr ng-show="fint.length > 0"><td colspan="8"><h3>International ({{fint.length}})</h3></td></tr>
<tr ng-repeat="t in fint = (int = (vm.assignmentLookups | filter: {isInternational: true}) | filter: vm.searchResultText)">
<td>{{$index + 1}}</td>
<td ng-bind-html="vm.highlight(t.title, vm.searchResultText)"></td>
<td ng-bind-html="vm.highlight(t.genericName, vm.searchResultText)"></td>
<td ng-bind-html="vm.highlight(t.mechanismsOfAction, vm.searchResultText)"></td>
<td ng-bind-html="vm.highlight(t.diseaseStateIndication, vm.searchResultText)"></td>
<td ng-bind-html="vm.highlight(t.assignedTo, vm.searchResultText)"></td>
<td ng-bind-html="t.lastPublished | date:'medium'"></td>
</tr>
</tbody>
Ответ 11
Фильтр может быть объектом JavaScript с полями, и вы можете иметь выражение как:
ng-repeat= 'item in list | filter :{property:value}'
Ответ 12
Возможно, я очень опаздываю, но это то, что я в итоге сделал. Я сделал очень общий фильтр.
angular.module('app.filters').filter('fieldFilter', function() {
return function(input, clause, fields) {
var out = [];
if (clause && clause.query && clause.query.length > 0) {
clause.query = String(clause.query).toLowerCase();
angular.forEach(input, function(cp) {
for (var i = 0; i < fields.length; i++) {
var haystack = String(cp[fields[i]]).toLowerCase();
if (haystack.indexOf(clause.query) > -1) {
out.push(cp);
break;
}
}
})
} else {
angular.forEach(input, function(cp) {
out.push(cp);
})
}
return out;
}
})
Тогда используйте это как это
<tr ng-repeat-start="dvs in devices | fieldFilter:search:['name','device_id']"></tr>
Ваше окно поиска будет как
<input ng-model="search.query" class="form-control material-text-input" type="text">
где name и device_id - свойства в dvs
Ответ 13
Я решил это просто:
<div ng-repeat="Object in List | filter: (FilterObj.FilterProperty1 ? {'ObjectProperty1': FilterObj.FilterProperty1} : '') | filter:(FilterObj.FilterProperty2 ? {'ObjectProperty2': FilterObj.FilterProperty2} : '')">