pcgilday
pcgilday

Reputation: 1031

ui-bootstrap pagination resetting current page on initialization

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

Answers (7)

Muhammad Umar
Muhammad Umar

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

Ariful Haque
Ariful Haque

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="&lsaquo;"
           next-text="&rsaquo;" first-text="&laquo;" last-text="&raquo;">
     </uib-pagination>
</div>

Now everything working perfectly.

Upvotes: 1

theluckyluke
theluckyluke

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

Mudassir Ali
Mudassir Ali

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

pcgilday
pcgilday

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

Housty
Housty

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

TommyMac
TommyMac

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

Related Questions