I am having trouble bining filters whilst maintaining correct pagination.
I am using a custom directive and ng-repeat to cycle through tasks.
HTML:
<input type="text" ng-model="searchText" class="form-control search-icon float-right" placeholder="Type to filter">
<select ng-model="clientSearch">
<option value="">All Clients</option>
<option value="1">All Client 1</option>
<option value="2">All Client 2</option>
<option value="3">All Client 3</option>
</select>
<task-pane ng-repeat="task in filterList | start: (currentPage - 1) * perPage | limitTo: perPage | filter: {client_id : clientSearch || undefined}: true" task-data="task" modal-open="modalOpen(task.id)"></task-pane>
<uib-pagination total-items="filterList.length" items-per-page="20" next-text="Next" previous-text="Previous" ng-model="currentPage" max-size="maxSize" class="pagination-sm" boundary-link-numbers="true"></uib-pagination>
And my JS for Controller:
.controller('TasksArchiveController', ['$http', '$scope', '$filter', '$uibModal', function($http, $scope, $filter, $uibModal) {
$http.post('../assets/js/ajax/tasks_ajax_router.php', 'action=getArchive', config = {
headers: {"Content-Type": "application/x-www-form-urlencoded"}
})
.then(function successCallBack(response) {
$scope.tasks = response.data.task_data;
$scope.perPage = 20;
$scope.setPage = function (pageNo) {
$scope.currentPage = pageNo;
};
$scope.maxSize = 5;
$scope.$watch('searchText', function (term) {
var obj = term;
$scope.filterList = $filter('filter')($scope.tasks, obj);
$scope.currentPage = 1;
});
}
}, function errorCallBack(response) {
console.log(response);
})
}])
.directive('taskPane', function() {
return {
restrict: 'E',
templateUrl: '../../assets/task_archive_pane.html',
scope: {
task: '=taskData',
modalOpen: '&modalOpen'
}
};
})
.filter('start', function () {
return function (input, start) {
if (!input || !input.length) { return; }
start = +start;
return input.slice(start);
};
})
When I type into searchFilter, filterList.length updates, therefore the total-items attribute of the pagination updates and the correct number of pages are shown and everything is in order.
However, using the clientSearch filter (updating the model by selecting from the dropdown) filters correctly, but I need to update the filterList length (presumably) so that the pagination is calculated properly.
EDIT: I have tried defining the uib-pagination attribute as the following, meaning it does always get the correct number of total items, yet the pagination still calculates the number of pages needed using the original number of items before filtering:
total-items="(filterList | filter: {client_id : clientSearch || undefined}: true | filter: {user_id: staffSearch.id || undefined }: true | filter: {department_id : departmentSearch || undefined}: true | filter: {task_type : typeSearch || undefined}: true).length"
Any help would be much appreciated.
I am having trouble bining filters whilst maintaining correct pagination.
I am using a custom directive and ng-repeat to cycle through tasks.
HTML:
<input type="text" ng-model="searchText" class="form-control search-icon float-right" placeholder="Type to filter">
<select ng-model="clientSearch">
<option value="">All Clients</option>
<option value="1">All Client 1</option>
<option value="2">All Client 2</option>
<option value="3">All Client 3</option>
</select>
<task-pane ng-repeat="task in filterList | start: (currentPage - 1) * perPage | limitTo: perPage | filter: {client_id : clientSearch || undefined}: true" task-data="task" modal-open="modalOpen(task.id)"></task-pane>
<uib-pagination total-items="filterList.length" items-per-page="20" next-text="Next" previous-text="Previous" ng-model="currentPage" max-size="maxSize" class="pagination-sm" boundary-link-numbers="true"></uib-pagination>
And my JS for Controller:
.controller('TasksArchiveController', ['$http', '$scope', '$filter', '$uibModal', function($http, $scope, $filter, $uibModal) {
$http.post('../assets/js/ajax/tasks_ajax_router.php', 'action=getArchive', config = {
headers: {"Content-Type": "application/x-www-form-urlencoded"}
})
.then(function successCallBack(response) {
$scope.tasks = response.data.task_data;
$scope.perPage = 20;
$scope.setPage = function (pageNo) {
$scope.currentPage = pageNo;
};
$scope.maxSize = 5;
$scope.$watch('searchText', function (term) {
var obj = term;
$scope.filterList = $filter('filter')($scope.tasks, obj);
$scope.currentPage = 1;
});
}
}, function errorCallBack(response) {
console.log(response);
})
}])
.directive('taskPane', function() {
return {
restrict: 'E',
templateUrl: '../../assets/task_archive_pane.html',
scope: {
task: '=taskData',
modalOpen: '&modalOpen'
}
};
})
.filter('start', function () {
return function (input, start) {
if (!input || !input.length) { return; }
start = +start;
return input.slice(start);
};
})
When I type into searchFilter, filterList.length updates, therefore the total-items attribute of the pagination updates and the correct number of pages are shown and everything is in order.
However, using the clientSearch filter (updating the model by selecting from the dropdown) filters correctly, but I need to update the filterList length (presumably) so that the pagination is calculated properly.
EDIT: I have tried defining the uib-pagination attribute as the following, meaning it does always get the correct number of total items, yet the pagination still calculates the number of pages needed using the original number of items before filtering:
total-items="(filterList | filter: {client_id : clientSearch || undefined}: true | filter: {user_id: staffSearch.id || undefined }: true | filter: {department_id : departmentSearch || undefined}: true | filter: {task_type : typeSearch || undefined}: true).length"
Any help would be much appreciated.
Share Improve this question edited Mar 21, 2016 at 15:13 DJC asked Mar 18, 2016 at 15:07 DJCDJC 1,1731 gold badge15 silver badges46 bronze badges 2- why you don't use angular ui pagination bootstrap ? – que1326 Commented Mar 21, 2016 at 20:17
- @VladRadulescu - I am. – DJC Commented Mar 21, 2016 at 20:28
2 Answers
Reset to default 5 +50First, you probably want to perform the client_id
filter before the pagination filters. Otherwise when you filter, you'll get pages of various small sizes as the client_id
filtering is being performed within each page. Also, when you make the change below to count the filter results, the count would be wrong as it would only count one page. So the order should be filter:
, start:
, limitTo:
Second, you need to store the results of the client_id
filter in a variable lets say filtered
, and the length of this is what should control the pagination via total-items
.
<task-pane ng-repeat="task in filtered = (filterList | filter: {client_id : clientSearch || undefined}: true) | start: (currentPage - 1) * perPage | limitTo: perPage" task-data="task" modal-open="modalOpen(task.id)"></task-pane>
<uib-pagination total-items="filtered.length" items-per-page="20" next-text="Next" previous-text="Previous" ng-model="currentPage" max-size="maxSize" class="pagination-sm" boundary-link-numbers="true"></uib-pagination>
Simplified fiddle here
Better option to go for it would be using variable alias
on filtered collection like ng-repeat="item in items | filter1: param | filter: {prop: param1} as filteredItem"
where as filteredItem
will store filtered value inside filteredItem
scope variable and you can use that scope variable wherever you want.
Markup
<task-pane ng-repeat="task in filterList | start: (currentPage - 1) * perPage | limitTo: perPage | filter: {client_id : clientSearch || undefined}: true as filteredList"
task-data="task" modal-open="modalOpen(task.id)">
</task-pane>
Pagination
<uib-pagination total-items="filteredList.length"
items-per-page="20" next-text="Next"
previous-text="Previous" ng-model="currentPage"
max-size="maxSize" class="pagination-sm"
boundary-link-numbers="true">
</uib-pagination>
Note: This feature has been supported in Angular 1.3+