I'm wondering if there's an easy way in Angular to filter a table using ng-repeat
on specific columns using or
logic, rather than and
. Right now, my filter is searching everything in the table (10+ columns of data), when it really only needs to filter on 2 columns of data (ID and Name).
我想知道是否有一种简单的方法可以在特定的列上使用ng-repeat来过滤表格,而不是使用and。现在,我的过滤器正在搜索表中的所有内容(10+列数据),而实际上它只需要过滤2列数据(ID和名称)。
I've managed to get it down to look only at those 2 columns when filtering (by using an object in the filter expression as per the docs and looking at this SO answer), but it's using and
logic, which is too specific. I'd like to get it to use or
logic, but am having trouble.
我已经设法让它在过滤时只查看这两列(通过在筛选表达式中使用一个对象,如文档中所示),但它是使用和逻辑,这太具体了。我很想把它用出来,但我遇到麻烦了。
My HTML
我的HTML
<input type="text" ng-model="filterText" />
<table>
<tr ng-repeat="item in data"><td>{{ item.id }}</td><td>{{ item.name }}</td>...</tr>
</table>
My filter logic:
我的过滤逻辑:
$filter('filter')(data, {id:$scope.filterText, name:$scope.filterText})
过滤器(“过滤器”)(数据,美元{ id:美元范围。filterText、名称:$ scope.filterText })
The filtering works, but again, it's taking the intersection of the matching columns rather than the union. Thanks!
过滤是有效的,但它取的是匹配列的交点而不是联合。谢谢!
8 个解决方案
#1
23
It's not hard to create a custom filter which allows you to have as many arguments as you want. Below is an example of a filter with one and two arguments, but you can add as many as you need.
创建一个自定义过滤器并不难,它允许您拥有任意数量的参数。下面是一个带有一个和两个参数的过滤器的示例,但是您可以添加任意数量的参数。
Example JS:
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;
});
}
}
});
Then in your HTML:
然后在你的HTML:
<tr ng-repeat="item in data | myTableFilter:filterText">
Or if you want to use multiple arguments:
或者如果你想使用多个参数:
<tr ng-repeat="item in data | myTableFilter:filterText:argumentTwo:argumentThree">
#2
20
Use this to search on All Columns (can be slow): search.$ AngularJS API: filter
使用它搜索所有列(可能很慢):搜索。美元AngularJS API:过滤器
Any Column Search:
<input ng-model="search.$">
<table>
<tr ng-repeat="friendObj in friends | filter:search:strict">
...
#3
6
To expand on the excellent answer by @charlietfl, here's a custom filter that filters by one column(property) which is passed to the function dynamically instead of being hard-coded. This would allow you to use the filter in different tables.
为了扩展@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;
});
}
}
});
Now on the mark-up side
现在在涨价方面
<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>
#4
3
I figured it out- I had to write my own custom filter. Here is my solution:
我想出来了——我必须编写自己的自定义过滤器。这是我的解决方案:
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;
}
});
#5
1
I created this filter to perform search in several fields:
我创建了这个过滤器来在几个字段中执行搜索:
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;
};
};
How to use:
如何使用:
<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
0
Easily We can do this type Following written code according you will easily create another field filter....
容易后我们可以做这种写的代码显示你会轻松地创建另一个字段过滤....
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
0
Here is my solution, it's very lazy, it will search on all strings in array on first level, you could update this to recusively go down the tree, but this should be good enough...
这是我的解决方案,它很懒,它会在第一级对数组中的所有字符串进行搜索,你可以更新它,让它重新沿着树向下移动,但这应该足够好了……
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
#1
23
It's not hard to create a custom filter which allows you to have as many arguments as you want. Below is an example of a filter with one and two arguments, but you can add as many as you need.
创建一个自定义过滤器并不难,它允许您拥有任意数量的参数。下面是一个带有一个和两个参数的过滤器的示例,但是您可以添加任意数量的参数。
Example JS:
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;
});
}
}
});
Then in your HTML:
然后在你的HTML:
<tr ng-repeat="item in data | myTableFilter:filterText">
Or if you want to use multiple arguments:
或者如果你想使用多个参数:
<tr ng-repeat="item in data | myTableFilter:filterText:argumentTwo:argumentThree">
#2
20
Use this to search on All Columns (can be slow): search.$ AngularJS API: filter
使用它搜索所有列(可能很慢):搜索。美元AngularJS API:过滤器
Any Column Search:
<input ng-model="search.$">
<table>
<tr ng-repeat="friendObj in friends | filter:search:strict">
...
#3
6
To expand on the excellent answer by @charlietfl, here's a custom filter that filters by one column(property) which is passed to the function dynamically instead of being hard-coded. This would allow you to use the filter in different tables.
为了扩展@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;
});
}
}
});
Now on the mark-up side
现在在涨价方面
<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>
#4
3
I figured it out- I had to write my own custom filter. Here is my solution:
我想出来了——我必须编写自己的自定义过滤器。这是我的解决方案:
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;
}
});
#5
1
I created this filter to perform search in several fields:
我创建了这个过滤器来在几个字段中执行搜索:
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;
};
};
How to use:
如何使用:
<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
0
Easily We can do this type Following written code according you will easily create another field filter....
容易后我们可以做这种写的代码显示你会轻松地创建另一个字段过滤....
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
0
Here is my solution, it's very lazy, it will search on all strings in array on first level, you could update this to recusively go down the tree, but this should be good enough...
这是我的解决方案,它很懒,它会在第一级对数组中的所有字符串进行搜索,你可以更新它,让它重新沿着树向下移动,但这应该足够好了……
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;
});
}
}
});