Reputation: 1031
I am using the pagination directive from the ui-bootstrap (angular-bootstrap) library. I am having an issue when it initializes. My issue occurs when I navigate to a specific page via url.
What is happening is that my controller initializes with the correct page from $stateParams, then the pagination directive initializes and triggers the ng-change function which is resetting the page to 1. Now that on-select-page is no longer used, is there a way to only capture user clicks to change the page? Ideally I would like the directive to initialize before the controller so that my page does not get reset. Thank you in advance.
I can include code if needed, but I feel my question does not necessarily require a code block.
Upvotes: 41
Views: 23146
Reputation: 1679
Just adding another simplest way to fix the problem. 1. First, pass query params to your URL(to make more sense about at which page you are currently at). To do this, add this line of code to your function that runs on (pageChange). i.e (pageChange)="getAllData(page)"
this.router.navigate(['/Advertisement'], { queryParams: { page: page }});
2. Second, get query params and assign the params to page variable. i.e
this.route.queryParamMap.subscribe((params:any) => { this.page = +params.get('page')});
My HTML
<ngb-pagination [collectionSize]="collectionSize" [(page)]="page" [pageSize]="pageSize" (pageChange)="getAdvertisements(page)">
Upvotes: 0
Reputation: 3750
A solution to this problem I've found from Github and implemented and worked perfectly.
As mentioned in other answers also, the issue is with totalItems
and when I try to move to page 2/3/n, totalItems
becomes 0 for a moment and in the process, currentPage
value becomes 1 and I can't move to my desired page. So my trick is, before I call the data from server, I just set a bigger number as totalItems
and after I receive data from server, I update totalItems
.
$scope.totalItems = 1000;
QuotationService.getQuotations(url).then(function ( response ) {
$scope.totalItems = response.data.total;
$scope.quotations = response.data.data;
$scope.isTableLoading = false;
});
In my view, only if isTableLoading
is false
, I show the Pagination, otherwise pagination will show a wrong number of pages.
<div class="text-center" ng-show="isTableLoading == false">
<uib-pagination boundary-links="true"
total-items="totalItems"
items-per-page="15" max-size="15" ng-model="currentPage"
class="pagination-sm" previous-text="‹"
next-text="›" first-text="«" last-text="»">
</uib-pagination>
</div>
Now everything working perfectly.
Upvotes: 1
Reputation: 81
The ng-if
directive didn't work for me as expected (I didn't use the controllerAs
syntax): the pagination wasn't able to update the $scope.currentPage
variable anymore. The solution was to use ng-model="$parent.currentPage"
instead of ng-model="currentPage"
.
<uib-pagination ng-if="totalItems"
total-items="totalItems"
items-per-page="itemsPerPage"
ng-model="$parent.currentPage">
</uib-pagination>
Upvotes: 8
Reputation: 8041
If you don't want to use state resolve the data then you could just add a ng-if
directive on paginator. Assuming $scope.total_count
is used to bind to total-items
attribute, you can do something like the following:
<pagination data-ng-if="total_count"
total-items="total_count"
ng-model="applied_filters.page"
max-size="maxSize"
class="pagination-sm"
boundary-links="true"
rotate="false"
class="nomargin"
num-pages="numPages"></pagination>
This way the directive is always initialized when you have total count from the server & currentPage will not be greater than totalPages
Upvotes: 41
Reputation: 1031
So I found a solution after drilling down into the angular-bootstrap code. Their code has a watch on totalPages that checks if the current page is greater than the totalPages value.
angular-bootstrap code:
if ( $scope.page > value ) {
$scope.selectPage(value);
} else {
ngModelCtrl.$render();
}
What was happening was if I refreshed the page on page 3 (for example) my controller was reloading the items for that page temporarily causing total-items to be 0 and totalPages to be calculated as 1. This triggered the watch and the above code.
My solution was to load the items in the state resolve so that total-items (and in turn totalPages) would always be accurate.
Upvotes: 45
Reputation: 56
An alternative to the state resolve would be to set the total-items in a value module once known. Same dealio, actually I just wanted to comment on your above answer, but I didn't have the points necessary. Thanks for the explanation, helped me out!
Upvotes: 0
Reputation: 299
If you are looking to set the page when the page loads, then just load up the model as it describes here.
From the website:
<pagination total-items="totalItems" ng-model="currentPage" ng-change="pageChanged()">
</pagination>
I'm sure you've already looked there, so if the model is not being set properly upon the initialization of the controller then you're obviously going to have problems. There is also the case where it is possibly being overwritten in another place where you are using $scope.currentPage
. Although you may feel it is easier without code, I would suggest posting the HTML and Angular Controller you are referring to. Hope it helps!
Upvotes: 0