Угловые фильтры: как предварительно отфильтровать так, чтобы угловые фильтры рассматривали только часть всего объекта данных
Я получил большую таблицу данных (которая получает свои данные из JSON api) с несколькими столбцами и хотел бы реализовать несколько фильтров, делая следующее:
- Возможность выбрать, какой столбец данных следует рассматривать (раскрывающийся список, содержащий опцию thead) [my columnFilter] и тогда
- поле ввода для фильтрации конкретных данных-partial [my searchFilter]
У меня работает поисковый фильтр, но я не знаю, как подключить columnFilter и сделать searchFilter применяется только к выбранным данным-частичным.
Итак, предположим, что я хотел бы видеть только описания, содержащие мир "синий".Как я могу связать эти два фильтра и заставить их работать?
Вот некоторые из моих кодов:
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>
И ссылка на рабочий поршень: http://plnkr.co/edit/TddllGiey0RmCx18eVdd?p=preview
3 ответа:
Насколько я знаю angular, есть два основных способа решить вашу проблему.
- определите пользовательский фильтр
- определите функцию для фильтрации данных и вызовите ее с помощью ng-show или ng-hide
Я получил большую таблицу данных
Если я хорошо понимаю, вы указываете это, потому что производительность-это большая проблема.
Есть хорошая статья, которая раскрывает различия между этими двумя решениями. : http://www.bennadel.com/blog/2487-filter-vs-nghide-with-ngrepeat-in-angularjs.htm
Поскольку производительность может быть действительно важна для вас, я предлагаю вам второй подход.На ваш взгляд:
<tbody ng-repeat="url in urls" ng-show="filterUrl(url)">
В вашем контроллере:
$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; } };
Обновление: Если вы выберете первый подход:
На ваш взгляд:
<tbody ng-repeat="url in urls | filterByColumn: searchFilter :columnFilter">
Фильтр:
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; }; });
Вот планкр: http://plnkr.co/edit/xCwI2AURFpvb6xHgYHxS?p=preview
Проверьте, как этот пример прямо с угловой страницы создания пользовательского фильтра. https://docs.angularjs.org/guide/filter
Здесь вы можете увидеть, что вы можете создать фильтр, который принимает 2 входных сигнала, фактический объект и параметр. Передавая имя столбца в качестве параметра, вы можете сузить поиск правильных строк.
Я бы рекомендовал вам написать простой пользовательский фильтр, подобный этому.
.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; }); }; });
Вы можете использовать этот фильтр в html.
ng-repeat="url in urls | myfilter:columnFilter:searchFilter"