Pagination on a list using ng-repeat

The question:

I’m trying to add pages to my list. I followed the AngularJS tutorial, the one about smartphones and I’m trying to display only certain number of objects. Here is my html file:

  <div class='container-fluid'>
    <div class='row-fluid'>
        <div class='span2'>
            Search: <input ng-model='searchBar'>
            Sort by: 
            <select ng-model='orderProp'>
                <option value='name'>Alphabetical</option>
                <option value='age'>Newest</option>
            You selected the phones to be ordered by: {{orderProp}}

        <div class='span10'>
          <select ng-model='limit'>
            <option value='5'>Show 5 per page</option>
            <option value='10'>Show 10 per page</option>
            <option value='15'>Show 15 per page</option>
            <option value='20'>Show 20 per page</option>
          <ul class='phones'>
            <li class='thumbnail' ng-repeat='phone in phones | filter:searchBar | orderBy:orderProp | limitTo:limit'>
                <a href='#/phones/{{}}' class='thumb'><img ng-src='{{phone.imageUrl}}'></a>
                <a href='#/phones/{{}}'>{{}}</a>

I’ve added a select tag with some values in order to limit the number of items that will be displayed. What I want now is to add the pagination to display the next 5, 10, etc.

I have a controller that works with this:

function PhoneListCtrl($scope, Phone){
    $scope.phones = Phone.query();
    $scope.orderProp = 'age';
    $scope.limit = 5;

And also I have a module in order to retrieve the data from the json files.

angular.module('phonecatServices', ['ngResource']).
    factory('Phone', function($resource){
        return $resource('phones/:phoneId.json', {}, {
            query: {method: 'GET', params:{phoneId:'phones'}, isArray:true}

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

If you have not too much data, you can definitely do pagination by just storing all the data in the browser and filtering what’s visible at a certain time.

Here’s a simple pagination example:

That example was on the list of fiddles on the angular.js github wiki, which should be helpful:

to (won’t show “1/4.5” if there is 45 results)

Method 2

I just made a JSFiddle that show pagination + search + order by on each column using
Build with Twitter Bootstrap code:

Method 3

I’ve built a module that makes in-memory pagination incredibly simple.

It allows you to paginate by simply replacing ng-repeat with dir-paginate, specifying the items per page as a piped filter, and then dropping the controls wherever you like in the form of a single directive, <dir-pagination-controls>

To take the original example asked by Tomarto, it would look like this:

<ul class='phones'>
    <li class='thumbnail' dir-paginate='phone in phones | filter:searchBar | orderBy:orderProp | limitTo:limit | itemsPerPage: limit'>
            <a href='#/phones/{{}}' class='thumb'><img ng-src='{{phone.imageUrl}}'></a>
            <a href='#/phones/{{}}'>{{}}</a>


There is no need for any special pagination code in your controller. It’s all handled internally by the module.


Source: dirPagination of GitHub

Method 4

I know this thread is old now but I am answering it to keep things a bit updated.

With Angular 1.4 and above you can directly use limitTo filter which apart from accepting the limit parameter also accepts a begin parameter.

Usage: {{ limitTo_expression | limitTo : limit : begin}}

So now you may not need to use any third party library to achieve something like pagination. I have created a fiddle to illustrate the same.

Method 5

Check out this directive:

It automates sorting and pagination a lot and gives you enough freedom to customize your table/list however you want.

Method 6

Here is a demo code where there is pagination + Filtering with AngularJS :

JS :

var app=angular.module('myApp', []);

// alternate -
// alternate -

app.controller('MyCtrl', ['$scope', '$filter', function ($scope, $filter) {
    $scope.currentPage = 0;
    $scope.pageSize = 10;
    $ = [];
    $scope.q = '';

    $scope.getData = function () {
      // needed for the pagination calc
      return $filter('filter')($, $scope.q)
       // manual filter
       // if u used this, remove the filter from html, remove above line and replace data with getData()

        var arr = [];
        if($scope.q == '') {
            arr = $;
        } else {
            for(var ea in $ {
                if($[ea].indexOf($scope.q) > -1) {
                    arr.push( $[ea] );
        return arr;

        return Math.ceil($scope.getData().length/$scope.pageSize);                

    for (var i=0; i<65; i++) {
        $"Item "+i);
  // A watch to bring us back to the 
  // first pagination after each 
  // filtering
$scope.$watch('q', function(newValue,oldValue){             if(oldValue!=newValue){
      $scope.currentPage = 0;

//We already have a limitTo filter built-in to angular,
//let's make a startFrom filter
app.filter('startFrom', function() {
    return function(input, start) {
        start = +start; //parse to int
        return input.slice(start);


<div ng-app="myApp" ng-controller="MyCtrl">
  <input ng-model="q" id="search" class="form-control" placeholder="Filter text">
  <select ng-model="pageSize" id="pageSize" class="form-control">
        <option value="5">5</option>
        <option value="10">10</option>
        <option value="15">15</option>
        <option value="20">20</option>
    <li ng-repeat="item in data | filter:q | startFrom:currentPage*pageSize | limitTo:pageSize">
  <button ng-disabled="currentPage == 0" ng-click="currentPage=currentPage-1">
    </button> {{currentPage+1}}/{{numberOfPages()}}
  <button ng-disabled="currentPage >= getData().length/pageSize - 1" ng-click="currentPage=currentPage+1">

All methods was sourced from or, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment