14

I am using ui-Bootstrap and I am trying to get the pagination working but I seem to be missing something. I have read the documentation and looked at a bunch of plunkers to try and work out how they are specifying which content to paginate but I am having no luck.

Here is what I have done http://plnkr.co/edit/5mfiAcOaGw8z8VinhIQo?p=preview

<section class="main" ng-controller="contentCtrl">
  <div ng-repeat="friend in friends">
    {{friend.name}}
  </div>
  <pagination total-items="totalItems" items-per-page="itemsPerPage" ng-model="currentPage" ng-change="pageChanged()"></pagination>

  <p>
    total Items: {{totalItems}}<br />
    Items per page: {{itemsPerPage}}<br />
    Current Page: {{currentPage}}
  </p>
</section>

Controller:

angular.module('plunker', ['ui.bootstrap'])
  .controller('contentCtrl', function ($scope) {

    $scope.friends = [
      {'name':'Jack'},
      {'name':'Tim'},
      {'name':'Stuart'},
      {'name':'Richard'},
      {'name':'Tom'},
      {'name':'Frank'},
      {'name':'Ted'},
      {'name':'Michael'},
      {'name':'Albert'},
      {'name':'Tobby'},
      {'name':'Mick'},
      {'name':'Nicholas'},
      {'name':'Jesse'},
      {'name':'Lex'},
      {'name':'Robbie'},
      {'name':'Jake'},
      {'name':'Levi'},
      {'name':'Edward'},
      {'name':'Neil'},
      {'name':'Hugh'},
      {'name':'Hugo'},
      {'name':'Yanick'},
      {'name':'Matt'},
      {'name':'Andrew'},
      {'name':'Charles'},
      {'name':'Oliver'},
      {'name':'Robin'},
      {'name':'Harry'},
      {'name':'James'},
      {'name':'Kelvin'},
      {'name':'David'},
      {'name':'Paul'}
    ];

    $scope.totalItems = 64;
    $scope.itemsPerPage = 10
    $scope.currentPage = 1;

    $scope.setPage = function (pageNo) {
      $scope.currentPage = pageNo;
    };

    $scope.pageChanged = function() {
      console.log('Page changed to: ' + $scope.currentPage);
    };

    $scope.maxSize = 5;
    $scope.bigTotalItems = 175;
    $scope.bigCurrentPage = 1;
  });
Daimz
  • 3,243
  • 14
  • 49
  • 76

4 Answers4

24

I could simply add the following references:

  1. bootstrap-css
  2. angular.js
  3. angular-ui-bootstrap

Your body could look like this:

<html ng-app="friends"> 
<head>
...
</head>
<body>
   <h4>Paginated Friends</h4>
   <section class="main" ng-controller="contentCtrl">
      <div ng-repeat="friend in filteredFriends">
         {{friend.name}}
      </div>
      <pagination total-items="totalItems" items-per-page="itemsPerPage" 
         ng-model="currentPage" ng-change="pageChanged()"></pagination>
      <p>
         Total items: {{totalItems}}<br />
         Items per page: {{itemsPerPage}}<br />
         Current Page: {{currentPage}}
      </p>
   </section>
</body>
</html>

Then define the following controller:

var app = angular.module('plunker', ['ngResource', 'ui.bootstrap']);

app.factory('friendsFactory', function($resource) {
  return $resource('friends.json');
});

app.controller('contentCtrl', function ($scope, friendsFactory) {
  $scope.friends = friendsFactory.query();

  $scope.itemsPerPage = 10
  $scope.currentPage = 1;

  // $scope.maxSize = 5;
  // $scope.bigTotalItems = 175;
  // $scope.bigCurrentPage = 1;

  $scope.pageCount = function () {
    return Math.ceil($scope.friends.length / $scope.itemsPerPage);
  };

  $scope.friends.$promise.then(function () {
    $scope.totalItems = $scope.friends.length;
    $scope.$watch('currentPage + itemsPerPage', function() {
      var begin = (($scope.currentPage - 1) * $scope.itemsPerPage),
        end = begin + $scope.itemsPerPage;

      $scope.filteredFriends = $scope.friends.slice(begin, end);
    });
  });
});
LordTribual
  • 4,219
  • 2
  • 28
  • 38
  • I tried this and I can get it updating the content except I end up with more pages that actual items. I updated the Plunker http://plnkr.co/edit/5mfiAcOaGw8z8VinhIQo?p=preview so you can see what I am talking about. Try clicking on anything about 6. – Daimz May 15 '14 at 09:57
  • 2
    Its because you set `$scope.totalItems` to 64 instead of using the following: `$scope.totalItems = $scope.friends.length;` Here i calculate the length of your friend list. If you just say it has 64 items even though it has not you will get of course 7 pages since 64 / 10 = 6,4 --> 7 pages. However your list only contains 32 items, thus you will get some empty pages. – LordTribual May 15 '14 at 12:00
  • Cool, I did actually manage to figure that one out, took me a while I just had to go through your code again and think about it logically. I do have one final problem. Now that I have the pagination working I want to call my 'friends' from a JSON file using ngResource, I can get the JSON Items to display with out pagination or I can get it to work with Pagination but no JSON file(the original way). I think the problem lies in 'filteredRecipes' as '$scope.recipes' shows correctly normally. I set up a Plunkr to try Illustrate http://plnkr.co/edit/AD1AGCYIm1dZhbuoPhxX?p=preview – Daimz May 15 '14 at 12:49
  • 1
    The data is not updated correctly because the watcher within the controller is fired before the query operation on your factory is finished. Thus you need to react on the $promise of the `$scope.friends` variable. I have updated my answer above. Check it out. – LordTribual May 15 '14 at 13:50
  • 1
    Your Awesome! This is perfect. For anyone looking for a working example check out this Plunkr http://plnkr.co/edit/AD1AGCYIm1dZhbuoPhxX?p=preview – Daimz May 15 '14 at 16:32
  • @Daimz You can remove your `$scope.totalItems = $scope.friends.length;` outside of the $promise since i moved it inside of it. – LordTribual May 16 '14 at 06:20
1

ui-bootstrap 0.10 doesn't use ng-model to update current page.

use page="currentPage" to show current page.

use on-select-page="setPage(page)" to change current page.

Example's here:

http://plnkr.co/edit/UIWIeDSKIK4bG96eoJmt?p=preview

if you want to use ng-model. update your ui-bootstrap version to 0.11

Bob Yuan
  • 588
  • 3
  • 14
  • 4
    Sorry I've only just started learning Angular, I'm not sure I understand exactly how this works. I can see it is updating "Current Page: 1" the it's not paginating the names and thats what is really confusing me, how can I connect the pagination so that it only shows 10 names and paginates the rest. – Daimz May 15 '14 at 09:46
1

You can use the variables that are created in your ng-repeat . This works. I use it until I have to change it.

ng-repeat="friend in friends.slice(((currentPage-1)*itemsPerPage), ((currentPage)*itemsPerPage)) track by $index"

However I have found that the best solution to this problem is to create a filter and chain it. Put it last in the chain since you would probably want to use other filters before it. Here is an example using an orderby filter. The difference is that you can then order your whole array and then paginate and show just the part that you would like to show.

function paginateFilter() {
  return function (friends, currentPage, itemsPerPage) {
    var filteredFlowers = flowers.slice(((currentPage-1)*itemsPerPage), ((currentPage)*itemsPerPage))
    return filteredFriends;
  };
}

And here is the html. You will have to use a filter with multiple variables.

ng-repeat="friend in main.friends |orderBy: 'name' | paginate: main.currentPage: main.itemsPerPage">

Where main is the controllerAs name.

rotato poti
  • 121
  • 1
  • 7
  • " I use it until I have to change it." Why change it? This is the best solution. Perfect! Thank you – Steven Aug 28 '16 at 20:32
0

implementation using angularjs 1.5 components and Typescript

searchresults.controller.ts

import {Group as Groups, GroupSearchCriteria as GroupsSearchCriteria, GroupSearchResults as GroupsSearchResults } from "../../models/Groups";
import GroupsService from "groups/groups.service";

interface ISearchResultsController {
    groups: Groups[];
    groupsSearchCriteria: GroupsSearchCriteria;
    pageChanged(): void;
    splitGroupsPagination(): void;
  }

class SearchResultsController implements ISearchResultsController {

    groups: Groups[];
    groupsSearchCriteria: GroupsSearchCriteria;
    groupresSearchCriteria: any;
    TotalResults: any;
    CurrentPage: any;
    ResultsPerPage: any;
    pageCount: number;
    begin: number;
    end: number;
    sortedResults: Groups[];

           constructor(private groupsService: GroupsService, private groupSearchResults: GroupsSearchResults) {
        var isolatedScopeSearchResults = this;
        this.groups = isolatedScopeSearchResults.groupsService.searchCallback.SearchResults;
        this.groupresSearchCriteria = isolatedScopeSearchResults.groupsService.searchCallback.Criteria;
        this.TotalResults = 7;
        this.CurrentPage = 1;
        this.ResultsPerPage = 5;
    }

    $onInit() {
        this.splitGroupsPagination();
    }

    splitGroupsPagination() {
        this.pageCount = Math.ceil(this.TotalResults / this.ResultsPerPage);
        this.begin = ((this.CurrentPage - 1) * this.ResultsPerPage);
        this.end = this.begin + this.ResultsPerPage;
        this.sortedResults = this.groups.slice(this.begin, this.end);
    }

    pageChanged() {
        this.splitGroupsPagination();
    }
}

export default SearchResultsController;

searchresults.component.ts

    import SearchResultsController from "./searchresults.controller";

    class SearchResultsComponent implements ng.IComponentOptions {
        template = `


    <div id="groupSearchResults" class="box-response">
      <!-- start: results header with btn add-->
        <div class="box-header">
            <h2><span>Search Results: </span><span>{{$ctrl.groups.length}}</span> <span>Term: {{$ctrl.groupresSearchCriteria.SearchDescription}}</span></h2>
        </div>

        <div class="box-content">


    <table class="table table-bordered table-hover table-striped">
        <thead>
            <tr>
                <td>Name</td>
                <td>Id</td>
                <td>Consent Group</td>
                <td>Permitted Uris</td>
                <td>Actions</td>
            </tr>
        </thead>
        <tbody>
            <tr data-ng-repeat="group in $ctrl.sortedResults">
                <td>{{group.Name}}</td>
                <td>{{group.Id}}</td>
                <td>{{group.IncludeInConsentGroups}}</td>
                <td>{{group.PermittedUris}}</td>
                <td>
                   <a class="btn btn-success" href="" ui-sref="edit({editgroupId:group.Id})"><i class="fa fa-edit"></i></a>
                </td>
            </tr>
        </tbody>
    </table>

    </div>

  <uib-pagination total-items="$ctrl.TotalResults" ng-model="$ctrl.CurrentPage" items-per-page="$ctrl.ResultsPerPage" ng-change="$ctrl.pageChanged()"></uib-pagination>

    </div>


       `;

        controller = ['GroupsService',SearchResultsController];
    }

    export default SearchResultsComponent;