Reputation: 1542
I'm new to Angular, so go easy on me.
My question is similar to this one. I'm doing something a little different, so the accepted answer isn't working for me.
I'm using Angular UI Bootstrap's Pagination directive to paginate a dataset, and I'm using Angular filters to allow users to filter data for any column.
The problem is that when the data is filtered, the user only sees the data on the page he's currently on.
$scope.applyFilter = function() {
var begin = (($scope.currentPage - 1) * $scope.itemsPerPage);
var end = begin + $scope.itemsPerPage;
$scope.totalItems = $filter('filter')($scope.items).length;
$scope.filteredItems = $filter('filter')($scope.items).slice(begin, end);
};
For example, if you key in a state of "GA" in the state filter (text box under the word "State"), no data is returned. However, you can select page 4 and see the one record that meets the condition.
What I would like to happen is for the pagination to automatically adjust, showing just one page of results with the correct record appearing to the user.
I know that there are other grid directives that already have this functionality, but I'd prefer to not completely abandon my current approach.
Upvotes: 0
Views: 1200
Reputation: 18513
You can use the limitTo filter for pagination in your ng-repeat.
e.g.
<tr ng-repeat="item in items | filter:search:strict | orderBy:propertyName:reverse | limitTo:5:(currentPage-1)*5" >
The tricky part is updating the number of pages to show in your pagination widget when the filter changes. You can do this by assigning the filtered items to a variable before the limitTo
filter is applied. e.g.
<tr ng-repeat="item in filteredItems = (items | filter:search:strict | orderBy:propertyName:reverse) | limitTo:5:(currentPage-1)*5" >
<ul uib-pagination total-items="filteredItems.length" ...></ul>
With this approach there is no need to $watch
anything or do any filtering in your controller.
Working plunkr: http://plnkr.co/edit/8NinIYdRsXDVLCPz5VJN?p=preview
Upvotes: 1
Reputation: 1420
I suggest you writing a custom pagination filter
app.filter('paginate', function() {
return function(items, currentPage, itemsPerPage) {
if (!Array.isArray(items)) {
return items;
}
var sliceStart = (currentPage - 1) * itemsPerPage;
return items.slice(sliceStart, sliceStart + itemsPerPage);
};
});
Moving filtering logics to the controller
$scope.applyFilter = function() {
var begin = (($scope.currentPage - 1) * $scope.itemsPerPage);
var end = begin + $scope.itemsPerPage;
$scope.filteredItems = $filter('filter')($scope.items, $scope.search);
$scope.filteredItems = $filter('orderBy')($scope.filteredItems, $scope.propertyName, $scope.reverse);
};
And finally updating your HTML in two places. Here
<tr ng-repeat="item in filteredItems | paginate : currentPage : itemsPerPage">
and here
<ul uib-pagination total-items="filteredItems.length" ng-model="currentPage" class="pagination-sm" boundary-links="true" force-ellipses="true" items-per-page="5" ></ul>
Upvotes: 1
Reputation: 1378
You forgot the parameter into your filters call
$scope.applyFilter = function() {
var begin = (($scope.currentPage - 1) * $scope.itemsPerPage);
var end = begin + $scope.itemsPerPage;
$scope.totalItems = $filter('filter')($scope.items, $scope.search).length;
$scope.filteredItems = ($filter('filter')($scope.items, $scope.search)).slice(begin, end);
};
Upvotes: 1