Google+

Pagination in web applications is a very common phenomenon and frequently used to split large result set into pages. The evolution of pagination with creativity has brought us from [1,2,3] to automatic pagination (like you see on google images). Naturally the number based pagination is becoming less and less common these days. We are seeing “Load more”, “Show more” type of pagination being adopted more perhaps. We’ll discuss about this in a separate UX article later. For today we will attempt to build something similar to “Show More” Pagination in AngularJS Framework.

Before we begin, we need a considerably large dataset. We have chosen typekit api to do the dirty job. Let’s get into code thing, shall we ?

As you can see here, we used one of the preferred angular code conventions, used $http and a factory as you can see below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
'use strict';

var App = angular.module('PaginationApp', ['services.SharedServices']);

App.controller('MainCtrl', ['$scope', '$filter', 'TypekitService', function ($scope, $filter, Typekit) {
    $scope.loadData = function () {
        var url = 'https://typekit.com/api/v1/json/libraries/full?page=' + $scope.page + '&per_page=' + $scope.per_page + '&callback=JSON_CALLBACK';
        Typekit.getTypekits(url).then(function (response) {
            $scope.more = response.data.library.families.length === $scope.per_page;
            $scope.families = $scope.families.concat(response.data.library.families);
            $scope.status_bar = "Showing " + ($scope.families.length === 0 ? "0" : "1") + " to " + $filter('number')($scope.families.length) + " of " + $filter('number')(response.data.library.pagination.count) + " entries";

        });
    }

    $scope.show_more = function () {
        $scope.page += 1;
        $scope.loadData();
    }

    $scope.has_more = function () {
        return $scope.more;
    }

    $scope.per_page = 10;
    $scope.page = 1;
    $scope.families = [];
    $scope.more = true;
    $scope.status_bar = "";
    $scope.loadData();
}]);

App.factory('TypekitService', ['$http', function ($http) {
    return {
        getTypekits: function (url) {
            return $http.jsonp(url);
        }
    }
}]);

/** Ajax Spinner **/
angular.module('services.SharedServices', []).config(function ($httpProvider) {
    $httpProvider.responseInterceptors.push('myHttpInterceptor');
    var spinnerFunction = function (data, headersGetter) {
        $("#loading").show();
        return data;
    };
    $httpProvider.defaults.transformRequest.push(spinnerFunction);
}).factory('myHttpInterceptor', function ($q, $window) {
    return function (promise) {
        return promise.then(function (response) {
            $("#loading").hide();
            return response;
        }, function (response) {
            $("#loading").hide();
            return $q.reject(response);
        });
    };
});

/** Ajax Spinner **/

First, we initialized angular module which invokes angular root elements for this application.

1
2
3
'use strict';

var App = angular.module('PaginationApp', ['services.SharedServices']);

MainCtrl is the main controller for this application with injection of $scope, $filter and TypeKitService. Where,
– $scope glue data model between view and controller
– $filter is used for formatting data displayed to the user and
– TypeKitService is a custom angular service which will return $http promise object.

The controller MainCtrl invoked from the view template

1
<div ng-controller="MainCtrl"></div>

We also, initialized some scope variable of controller MainCtrl. All of those scope variable are self explanatory.

1
2
3
4
5
6
$scope.per_page = 10;
$scope.page = 1;
$scope.families = [];
$scope.more = true;
$scope.status_bar = "";
$scope.loadData();

TypekitService is a custom angular service and getTypekits is a method of it which takes URL as a parameter. For, different domain data source we had to use JSONP $http service provider which return a promise.

1
$http.jsonp(url);

Now, Typekit service is ready to providing us the JSON object with a promise callback. We used $scope.families scope variable for storing the returned JSON data object.

1
$scope.families = $scope.families.concat(response.data.library.families);

If you look carefully then you will see, we used array concatenation to concatenating returned data with $scope.families array’s existing data. In the template portion we used an ng-repeat directive to iterate through the object and come up with a view.

1
2
3
4
5
<tr ng-repeat="family in families">
           <td><span class="badge">{{family.id}}</span></td>
           <td>{{family.name}}</td>
<td>{{family.link}}</td>
</tr>

For each and every click on the Show more button we increased the current page number and sent a request to the server.

1
2
3
4
$scope.show_more = function () {
       $scope.page += 1;
       $scope.loadData();
}

In template portion we used angular ng-click directive to binding that function.

1
<button class="btn btn-info" ng-show="has_more()" ng-click="show_more()"><i class="icon-plus icon-white"></i> Show More</button>

We also made the Show more button hidden if it has no more page to paginate.

1
2
3
$scope.has_more = function () {
       return $scope.more;
}

-which return $scope.more boolean scope variable and it’s also updated after each request.

1
$scope.more = response.data.library.families.length === $scope.per_page;

In the template part we used angular ng-show directive to binding that function.

1
<button class="btn btn-info" ng-show="has_more()" ng-click="show_more()"><i class="icon-plus icon-white"></i> Show More</button>

We also added pagination status message in both top and bottom of the records.

1
$scope.status_bar = "Showing " + ($scope.families.length === 0 ? "0" : "1") + " to " + $filter('number')($scope.families.length) + " of " + $filter('number')(response.data.library.pagination.count) + " entries";

Finally, we bind $scope.status_bar scope variable with our view template.

1
<div class="alert alert-success pull-left small">{{status_bar}}</div>

In addition, we also added an Ajax spinner to show loading message when a request is send to the server.

Here is a screenshot how it looks like.

Pagination in AngularJS for Typekit API

That wasn’t that difficult, was it ? Any questions, improvements, suggestions – you know what to do :-).


Post Meta

Comment(s):
0
Posted on:
March 4, 2013
Category:
AngularJS, JS
Tags:
, , , , , ,