可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I got a large data table (which gets its data from a json api) with multiple columns and would like to implement multiple filters doing the following:
- an option to select which data-column should be considered (a dropdown containing the thead option) [my columnFilter] and then
- an input field to filter that particular data-partial [my searchFilter]
I've got the searchFilter working, but I'm not sure how to connect the columnFilter and make the searchFilter only apply to the selected data-partial.
So let's say I'd like to only see Descriptions containing the world "blue".
How can I bind these two filters and make this work?
Here is some of my code:
Select data column: <select ng-model="columnFilter" ng-options="heading for heading in headings"> </select> </div> <div class="col-sm-12"> Filter selection: <input type='text' ng-model="searchFilter" /> </div> <table class="table table-bordered"> <thead> <tr> <th>URL</th> <th>Title</th> <th>Traffic</th> <th>Description</th> <th>ID</th> </tr> </thead> <tbody ng-repeat="url in urls | filter:searchFilter"> <tr> <td>{{url.url}}</td> <td>{{url.title}}</td> <td>{{url.traffic}}</td> <td>{{url.descr}}</td> <td>{{url.id}}</td> </tr> </tbody> </table>
and a link to a working plunker: http://plnkr.co/edit/TddllGiey0RmCx18eVdd?p=preview
回答1:
As far as i know angular, there is two main way to solve your problem.
- define a custom a filter
- define a function to filter your data and call it with ng-show or ng-hide
I got a large data table
If i understand well, you specify that because performance is a big issue.
There is a good article which exposes the differences between those two solutions : http://www.bennadel.com/blog/2487-filter-vs-nghide-with-ngrepeat-in-angularjs.htm
As performance may be really important for you, i suggest you the second approach.
In your view:
<tbody ng-repeat="url in urls" ng-show="filterUrl(url)">
In your controller:
$scope.searchFilter = ""; $scope.columnFilter = $scope.headings[5]; $scope.filterUrl = function(url){ if(!$scope.searchFilter || $scope.searchFilter == "") return url; var searchFilter= $scope.searchFilter.toLowerCase(); var trafficString = url.traffic.toString(); var idString = url.traffic.toString(); switch($scope.columnFilter){ case $scope.headings[0]: return url.title.toLowerCase().indexOf(searchFilter) != -1; case $scope.headings[1]: return url.url.toLowerCase().indexOf(searchFilter) != -1; case $scope.headings[2]: return trafficString.indexOf(searchFilter) != -1; case $scope.headings[3]: return url.descr.toLowerCase().indexOf(searchFilter) != -1; case $scope.headings[4]: return idString.indexOf(searchFilter) != -1; case $scope.headings[5]: return url.title.toLowerCase().indexOf(searchFilter) != -1 || url.url.toLowerCase().indexOf(searchFilter) != -1 || trafficString.indexOf(searchFilter) != -1 || url.descr.toLowerCase().indexOf(searchFilter) != -1 || idString.indexOf(searchFilter) != -1; } };
Update: If you choose the first approach:
In your view:
<tbody ng-repeat="url in urls | filterByColumn: searchFilter :columnFilter">
The filter:
app.filter('filterByColumn', function(){ return function(urls, text, columnFilter){ var processed = []; if(!text || text == "") return urls; urls.forEach(function(url){ var searchFilter= text.toLowerCase(); var trafficString = url.traffic.toString(); var idString = url.traffic.toString(); switch(columnFilter){ case "Title": if( url.title.toLowerCase().indexOf(searchFilter) != -1) processed.push(url); break; case "Url": if(url.url.toLowerCase().indexOf(searchFilter) != -1) processed.push(url); break; case "Traffic": if(trafficString.indexOf(searchFilter) != -1) processed.push(url); break; case "Description": if(url.descr.toLowerCase().indexOf(searchFilter) != -1) processed.push(url); break; case "Id": if( idString.indexOf(searchFilter) != -1) processed.push(url); break; case "All": if( url.title.toLowerCase().indexOf(searchFilter) != -1 || url.url.toLowerCase().indexOf(searchFilter) != -1 || trafficString.indexOf(searchFilter) != -1 || url.descr.toLowerCase().indexOf(searchFilter) != -1 || idString.indexOf(searchFilter) != -1) processed.push(url); break; } }); return processed; }; });
Here is a plunkr: http://plnkr.co/edit/xCwI2AURFpvb6xHgYHxS?p=preview
回答2:
Check how this example straight from the angular page of a creating a custom filter. https://docs.angularjs.org/guide/filter
You can see here that you can create a filter that accepts 2 inputs, the actual object and a parameter. By passing the column name as parameter, you can narrow down your search for the correct rows.
回答3:
I would recommend you to write simple custom filter like this.
.filter('myfilter', function(){ return function(input, column, text){ if (!input || !column || !text) return input; return input.filter(function(item){ var value = item[column.toLowerCase()]; if (!value)return false; return value.indexOf(text)>-1; }); }; });
You can use this filter in html.
ng-repeat="url in urls | myfilter:columnFilter:searchFilter"
This is plunker.