10

I have been continuing learning angular and have now used the angular ui bootstrap pagination successfully. I am able to display the list of items together with the correct number of pages. And also switch to the correct page whenever I click on the pagination.

Now my question is if a user wanted to bookmark a certain page, or to make sure the user stays on the same page whenever he refreshes the browser, how do I go about it. There are no links (href) being generated on the address bar of the browser. Do I also need to set routes? Can you please post some examples, as it would greatly help me. Thanks.

lynkyle
  • 221
  • 4
  • 10
  • Use HTML5 [History API](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history) so that the URL is the serialized state of your web application. – Matija Grcic May 11 '14 at 13:28

5 Answers5

12

You need to set up routes, you can do it using routeProvider or ui router

In this example, I use route provider to demonstrate, but the idea is the same.

Here I set up a route with currentPage as parameter:

app.config(function($routeProvider) {
  $routeProvider
    .when('/page/:currentPage', {
        templateUrl: "template.html",
        controller: PaginationDemoCtrl
    })
});

In your controller, you can retrieve the current page from $routeParam:

$scope.currentPage = $routeParams.currentPage || 1; //default to 1 if the parameter is missing
//load your paged data from server here.

You could just $watch current page for changes and update the location accordingly:

$scope.$watch("currentPage",function(value){
     if (value){
        $location.path("/page/" + value);
     }
  })

Source code

DEMO link

With routing, you also need to update your code to load paged data from server. We don't load data immediately when the currentPage changes (in this case is the $watch function). We load our paged data when we retrieve the $routeParam.currentPage parameter.

As requested by @Harry, here is another solution to generate href links by overwriting bootstrap html template:

app.config(function($routeProvider) {
  $routeProvider
    .when('/page/:currentPage?', {
        templateUrl: "template.html",
        controller: PaginationDemoCtrl
    })
})
.run(["$templateCache","$rootScope","$location", function($templateCache,$rootScope,$location) {

  $rootScope.createPagingLink = function(pageNumber){
    return "#" + $location.path().replace(/([0-9])+/,pageNumber);
//Here is a sample function to build href paths. In your real app, you may need to improve this to deal with more case.
  }

  $templateCache.put("template/pagination/pagination.html",
    "<ul class=\"pagination\">\n" +
    "  <li ng-if=\"boundaryLinks\" ng-class=\"{disabled: noPrevious()}\"><a ng-href=\"{{$root.createPagingLink(1)}}\">{{getText('first')}}</a></li>\n" +
    "  <li ng-if=\"directionLinks\" ng-class=\"{disabled: noPrevious()}\"><a ng-href=\"{{$root.createPagingLink(page - 1)}}\">{{getText('previous')}}</a></li>\n" +
    "  <li ng-repeat=\"page in pages track by $index\" ng-class=\"{active: page.active}\"><a ng-href=\"{{$root.createPagingLink(page.number)}}\">{{page.text}}</a></li>\n" +
    "  <li ng-if=\"directionLinks\" ng-class=\"{disabled: noNext()}\"><a ng-href=\"{{$root.createPagingLink(page + 1)}}\">{{getText('next')}}</a></li>\n" +
    "  <li ng-if=\"boundaryLinks\" ng-class=\"{disabled: noNext()}\"><a ng-href=\"{{$root.createPagingLink(totalPages)}}\">{{getText('last')}}</a></li>\n" +
    "</ul>");
}]);

Source code

DEMO link

Khanh TO
  • 48,509
  • 13
  • 99
  • 115
  • Still doesn't change your href. – Harry May 11 '14 at 09:51
  • @Harry: sorry, I don't understand what you mean. Please specify. – Khanh TO May 11 '14 at 09:54
  • You're changing the url in javascript, which is not good practice. You need proper links so that bots can index it correctly. – Harry May 11 '14 at 10:01
  • 1
    @Harry: I agree that using rendering proper hrefs is good in this case (changing route url). Fortunately, It looks like that bots now run js: http://stackoverflow.com/questions/19287476/why-do-search-engine-crawlers-not-run-javascript – Khanh TO May 11 '14 at 10:07
  • @Harry: if bots could not run JS, bots could not index angular applications either. – Khanh TO May 11 '14 at 10:14
  • Even if the bot can run js, which my phantomjs bot certainly can, it will not index the link if it's missing the href. – Harry May 11 '14 at 10:21
  • @Harry: yes, that's true. Anyway, this question is not about bots indexing. – Khanh TO May 11 '14 at 12:02
  • The question is about generating links and you're advising something that's bad practice. :D – Harry May 11 '14 at 12:09
  • @Harry: I'm not sure if it makes sense to index all pages of a list like that. Imagine a situation when there is a lot more content on the page besides the list. In this case, bots will index also these content for each page. Should we provide a html snapshot containing all records when bots visit our page? – Khanh TO May 11 '14 at 12:13
  • @Harry: it's possible to overwrite bootstrap's template to render hrefs. I'm still trying to remove the hardcoded "/page" in the href using something dynamic like $location.path(). See my edit – Khanh TO May 11 '14 at 13:25
  • 1
    @Harry: See my edit with a solution to build href as you requested (remove the hardcoded "/page" by using location.path()) – Khanh TO May 11 '14 at 14:15
  • Thanks I ended up replacing the entire directive. I'll give you the bounty when I'm allowed to in 15 hours. – Harry May 11 '14 at 15:02
2

We can do this with the $location, without needing $route.

Here is an example of how to call the pagination from Angular UI Bootstrap:

<pagination ng-model="Controls.currentPage"
            total-items="Controls.totalItems"
            items-per-page="Controls.videosPerPage"
            max-size="5"
            rotate="false"
            boundary-links="true"
            ng-change="pageChanged()">
</pagination>

Inside the pageChanged() function, use the following to create a unique URL for your results page:

** My code is on Coffeescript, but the logic is simple and the code easy to adapt **

$location.search('page', $scope.Controls.currentPage)

And on your controller, use the following to check, when starting, if the URL parameter is there:

urlParams = $location.search()
if urlParams.page?
  $scope.Controls.currentPage = urlParams.page
else
  $scope.Controls.currentPage = 1
pedrorocha
  • 141
  • 3
0

Yes, if you want your app to allow linking into certain states then you will have to have your app leverage the routeProvider.

The official docs don't have a great deal of information on routes but the tutorial has this page:

http://docs.angularjs.org/tutorial/step_07

Also John Lindquist's excellent short video tutorials are a must watch. One dealing with routes is:

http://www.egghead.io/video/gNtnxRzXj8s

Joc
  • 1,059
  • 8
  • 8
  • Thank you for your answer. Yes, I have watched several excellent videos of John Lindquist and I'll be sure I can use the stuff he shared on those videos. But my primary question was how should I go about generating links using the angular ui pagination? Sorry if it was not clear on my post above. – lynkyle May 30 '13 at 05:54
0

Here the generic solution - the uibPagination directive decorator and the updated template:

angular.module('ui.bootstrap.pagination')
    .config(function($provide) {
        $provide.decorator('uibPaginationDirective', function($delegate, $templateCache) {
            var directive = $delegate[0];
            directive.scope.getPageHref = "&";
            $templateCache.put("uib/template/pagination/pagination.html",
                "<li ng-if=\"::boundaryLinks\" ng-class=\"{disabled: noPrevious()||ngDisabled}\" class=\"pagination-first\"><a ng-href=\"{{noPrevious() ? '' : getPageHref()(1)}}\" ng-disabled=\"noPrevious()||ngDisabled\" uib-tabindex-toggle>{{::getText('first')}}</a></li>\n" +
                "<li ng-if=\"::directionLinks\" ng-class=\"{disabled: noPrevious()||ngDisabled}\" class=\"pagination-prev\"><a ng-href=\"{{noPrevious() ? '' : getPageHref()(page - 1)}}\" ng-disabled=\"noPrevious()||ngDisabled\" uib-tabindex-toggle>{{::getText('previous')}}</a></li>\n" +
                "<li ng-repeat=\"page in pages track by $index\" ng-class=\"{active: page.active,disabled: ngDisabled&&!page.active}\" class=\"pagination-page\"><a ng-href=\"{{getPageHref()(page.number)}}\" ng-disabled=\"ngDisabled&&!page.active\" uib-tabindex-toggle>{{page.text}}</a></li>\n" +
                "<li ng-if=\"::directionLinks\" ng-class=\"{disabled: noNext()||ngDisabled}\" class=\"pagination-next\"><a ng-href=\"{{noNext() ? '' : getPageHref()(page + 1)}}\" ng-disabled=\"noNext()||ngDisabled\" uib-tabindex-toggle>{{::getText('next')}}</a></li>\n" +
                "<li ng-if=\"::boundaryLinks\" ng-class=\"{disabled: noNext()||ngDisabled}\" class=\"pagination-last\"><a ng-href=\"{{noNext() ? '' : getPageHref()(totalPages)}}\"  ng-disabled=\"noNext()||ngDisabled\" uib-tabindex-toggle>{{::getText('last')}}</a></li>\n" +
                "");
            return $delegate;
        });
    });

We decorate the directive with the getPageHref function passed from the outer scope which is used to construct the page links.

Usage:

<div ng-controller="ProductController">
    ...
    <ul uib-pagination
        total-items="totalItems"
        ng-model="page"
        get-page-href="getPageHref">
    </ul>
</div>

Now you have to define the getPageHref function in your outer scope:

angular.module('app')
.controller('ProductController', function($scope) {
    ...
    $scope.getPageHref = function(page) {
        return '#/products?page=' + page;
    };
});
Alexander Kravets
  • 4,245
  • 1
  • 16
  • 15
0

Just to make code look better you can use template-url attribute on uib-pagination element to specify your new template url

I whould use ui-sref instead of using a function to generate the link .

and instead of reloading the controller for each page click pass a function for ng-click with $eventso you could prevent the href from been executed with e.preventDefault() and calling your ajax before

<li ng-repeat="page in pages track by $index" ng-class="{active: page.active}"><a ui-sref="list({page: page.text})"  ng-click="$root.paginationClick(page.number,$event)">{{page.text}}</a></li>
ilan weissberg
  • 658
  • 1
  • 7
  • 13