Фильтровать по нескольким столбцам с помощью ng-repeat
Мне интересно, есть ли простой способ в Angular для фильтрации таблицы с использованием ng-repeat
в определенных столбцах с использованием логики or
, а не and
. Прямо сейчас мой фильтр ищет все в таблице (10 + столбцы данных), когда ему действительно нужно только фильтровать по 2 столбцам данных (ID и Name).
Мне удалось получить его, чтобы посмотреть только на те 2 столбца при фильтрации (с помощью объекта в выражении фильтра в соответствии с документами и посмотрев этот ответ SO), но он использует логику and
, которая слишком специфична. Я бы хотел, чтобы он использовал логику or
, но у меня проблемы.
Мой HTML
<input type="text" ng-model="filterText" />
<table>
<tr ng-repeat="item in data"><td>{{ item.id }}</td><td>{{ item.name }}</td>...</tr>
</table>
Моя логика фильтра:
$filter('filter')(data, {id:$scope.filterText, name:$scope.filterText})
Фильтрация работает, но опять же, она пересекает совпадающие столбцы, а не объединение. Спасибо!
Ответы
Ответ 1
Я понял это - мне пришлось написать собственный собственный фильтр. Вот мое решение:
var filteredData;
filteredData = $filter('filter')(data, function(data) {
if ($scope.filter) {
return data.id.toString().indexOf($scope.filter) > -1 || data.name.toString().indexOf($scope.filter) > -1;
} else {
return true;
}
});
Ответ 2
Не сложно создать настраиваемый фильтр, который позволит вам иметь столько аргументов, сколько захотите. Ниже приведен пример фильтра с одним и двумя аргументами, но вы можете добавить столько, сколько вам нужно.
Пример JS:
var app = angular.module('myApp',[]);
app.filter('myTableFilter', function(){
// Just add arguments to your HTML separated by :
// And add them as parameters here, for example:
// return function(dataArray, searchTerm, argumentTwo, argumentThree) {
return function(dataArray, searchTerm) {
// If no array is given, exit.
if (!dataArray) {
return;
}
// If no search term exists, return the array unfiltered.
else if (!searchTerm) {
return dataArray;
}
// Otherwise, continue.
else {
// Convert filter text to lower case.
var term = searchTerm.toLowerCase();
// Return the array and filter it by looking for any occurrences of the search term in each items id or name.
return dataArray.filter(function(item){
var termInId = item.id.toLowerCase().indexOf(term) > -1;
var termInName = item.name.toLowerCase().indexOf(term) > -1;
return termInId || termInName;
});
}
}
});
Затем в вашем HTML:
<tr ng-repeat="item in data | myTableFilter:filterText">
Или если вы хотите использовать несколько аргументов:
<tr ng-repeat="item in data | myTableFilter:filterText:argumentTwo:argumentThree">
Ответ 3
Используйте это для поиска по всем столбцам (может быть медленным): поиск. $
AngularJS API: фильтр
Any Column Search:
<input ng-model="search.$">
<table>
<tr ng-repeat="friendObj in friends | filter:search:strict">
...
Ответ 4
Чтобы расширить отличный ответ от @charlietfl, здесь настраивается фильтр, который фильтрует один столбец (свойство), который динамически передается функции, а не жестко закодирован. Это позволит вам использовать фильтр в разных таблицах.
var app=angular.module('myApp',[]);
app.filter('filterByProperty', function () {
/* array is first argument, each addiitonal argument is prefixed by a ":" in filter markup*/
return function (dataArray, searchTerm, propertyName) {
if (!dataArray) return;
/* when term is cleared, return full array*/
if (!searchTerm) {
return dataArray
} else {
/* otherwise filter the array */
var term = searchTerm.toLowerCase();
return dataArray.filter(function (item) {
return item[propertyName].toLowerCase().indexOf(term) > -1;
});
}
}
});
Теперь на стороне разметки
<input type="text" ng-model="filterText" />
<table>
<tr ng-repeat="item in data |filterByProperty:filterText:'name'"><td>{{ item.id }}</td><td>{{ item.name }}</td>...</tr>
</table>
Ответ 5
Я создал этот фильтр для выполнения поиска в нескольких полях:
var find = function () {
return function (items,array) {
var model = array.model;
var fields = array.fields;
var clearOnEmpty = array.clearOnEmpty || false;
var filtered = [];
var inFields = function(row,query) {
var finded = false;
for ( var i in fields ) {
var field = row[fields[i]];
if ( field != undefined ) {
finded = angular.lowercase(row[fields[i]]).indexOf(query || '') !== -1;
}
if ( finded ) break;
}
return finded;
};
if ( clearOnEmpty && model == "" ) return filtered;
for (var i in items) {
var row = items[i];
var query = angular.lowercase(model);
if (query.indexOf(" ") > 0) {
var query_array = query.split(" ");
var x;
for (x in query_array) {
query = query_array[x];
var search_result = true;
if ( !inFields(row,query) ) {
search_result = false;
break;
}
}
} else {
search_result = inFields(row,query);
}
if ( search_result ) {
filtered.push(row);
}
}
return filtered;
};
};
Как использовать:
<tr repeat="item in colletion
| find: {
model : model, // Input model
fields : [ // Array of fields to filter
'FIELD1',
'FIELD2',
'FIELD3'
],
clearOnEmpty: true // Clear rows on empty model (not obligatory)
} "></tr>
Ответ 6
Легко Мы можем сделать этот тип После написания кода в соответствии с этим вы легко создадите еще один фильтр поля....
var myApp = angular.module('myApp',[]);
myApp.filter('myfilter',myfilter);
function myfilter(){
return function (items, filters) {
if (filters == null) {
return items;
}
var filtered = [];
//Apply filter
angular.forEach(items, function (item) {
if ((filters.Name == '' || angular.lowercase(item.Name).indexOf(angular.lowercase(filters.Name)) >= 0)
)
{
filtered.push(item);
}
});
return filtered;
};
}
myApp.controller('mycontroller',['$scope',function($scope){
$scope.filters={Name:'',MathsMarks:''};
$scope.students=[];
var i=0;
for(i=0;i<5;i++){
var item={Name:'',Marks:[]};
item.Name='student' + i;
item.Marks.push({Maths:50-i,Science:50 +i});
$scope.students.push(item);
}
}]);
<html ng-app='myApp'>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script>
</head>
<body ng-controller='mycontroller'>
<input type='text' name='studentName' ng-model="filters.Name" placeholder='Enter Student Name'>
<div ng-repeat="student in students | myfilter: filters">
Name : {{student.Name}} Marks == >
<span ng-repeat="m in student.Marks">Maths:{{m.Maths}} Science:{{m.Science}}</span>
</div>
</body>
</html>
Ответ 7
Вот мое решение, это очень лениво, он будет искать по всем строкам в массиве на первом уровне, вы можете обновить это, чтобы вкрадце пойти по дереву, но это должно быть достаточно хорошо...
app.filter('filterAll', function () {
return function (dataArray, searchTerm, propertyNames) {
if (!dataArray) return;
if (!searchTerm) {
return dataArray;
} else {
if (propertyNames == undefined) {
propertyNames = [];
for (var property in dataArray[0]) {
if(typeof dataArray[0][property] == "string" &&
property != "$$hashKey" &&
property != "UnitName" )
propertyNames.push(property);
}
}
console.log("propertyNames", propertyNames);
var term = searchTerm.toLowerCase();
return dataArray.filter(function (item) {
var found = false;
propertyNames.forEach(function(val) {
if (!found) {
if (item[val] != null && item[val].toLowerCase().indexOf(term) > -1)
found = true;
}
});
return found;
});
}
}
});
Ответ 8
см. эта ссылка. Отфильтруйте свойства нескольких объектов вместе в AngularJS