This tutorial will show us how to implement Server Side Pagination in our AngularJS applications. In any application when dealing with a list or tabular data, you would probably need pagination.
We have already seen in one of our previous articles how we can implement client side pagination in AngularJs with ease. Although server-side pagination sounds to be difficult but it won’t after you follow this article.
Concept
When working with asynchronous pagination, we fetch only one page of data at a time from the server. So if the user has clicked on page two we will fetch the result set only for page 2.
Overview
At the client side again we will be using dir-paginate like we did for client-side pagination. The API that returns us the data will take two parameters, the page number and items per page. So for example, if you are on your 2nd page and the items displayed per page is 10 the api should return 10 items starting from 11th position. Along with the data, the API will also return the count of total data. The total count is crucial for creating the pagination links. An alternative way is to pass the offset (Position of the result from which the data should be returned) instead of the page number.
Pagination API explanation
The API or method used to return the paginated data would require 2 parameters for our demo. The page number for which the data is requested and the number of items per page.
The API structure would be some thing like this.
http://yourdomain/apiname/{itemsPerPage}/{pagenumber}
Depending on the values of the itemsPerPage and pagenumber you will make appropriate request to your database. For example.
If your {itemsPerPage} is 10 and {pagenumber} is 3. Your API would look like this.
http://yourdomain/apiname/10/3.
And your corresponding MySQL query would be.
SELECT * FROM 'table_name' LIMIT ({pagenumber}-1)*{itemsPerPage},{itemsPerPage}
That results in.
SELECT * FROM 'table_name' LIMIT 20,10
This would return you rows from 21 to 30 (MySQL starts from 0) that would be your 3rd page. And if you are using offset as a parameter instead of pagenumber, you can simply do LIMIT {offset}-1,{itemsPerPage}, again -1 because the 1st row is the 0th position in MySQL.
Implementation
First we need to grab the required files and set up our HTML. We need dirPagination.js for our pagination. If you are using bower, you can download the files by running.
bower install angular-utils-pagination
Alternatively you can download it from the below link.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Server Pagination in Angular js</title>
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/bootstrap-theme.min.css">
<link rel="stylesheet" type="text/css" href="css/styles.css">
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.1/angular.js"></script>
<script src="lib/dirPagination.js"></script>
<script src="app/app.js"></script>
</body>
</html>
var app = angular.module('angularTable', ['angularUtils.directives.dirPagination']);
app.controller('listdata',function($http){
var vm = this;
vm.users = []; //declare an empty array
vm.pageno = 1; // initialize page no to 1
vm.total_count = 0;
vm.itemsPerPage = 10; //this could be a dynamic value from a drop down
vm.getData = function(pageno){ // This would fetch the data on page change.
//In practice this should be in a factory.
vm.users = []; $http.get("http://yourdomain/apiname/{itemsPerPage}/{pagenumber}").success(function(response){
//ajax request to fetch data into vm.data
vm.users = response.data; // data to be displayed on current page.
vm.total_count = response.total_count; // total data count.
});
};
vm.getData(vm.pageno); // Call the function to fetch initial data on page load.
});
- vm.users – Will hold the set of data to be displayed on the page.
- vm.pageno – Sets the page to 1 on load.
- vm.total_count – Stores the total no. of results, this value will be returned by the API
- vm.itemsPerPage – Number of items to be displayed per page. (Can be made dynamic )
- vm.getData() – Is a function that will fetch us the result every-time the user clicks on a new page. We also call this function once on load to fetch the data for page 1
Now that we have our controller setup lets complete our markup.
So to repeat on the data set, we will use the dir-paginate directive instead of ng-repeat. We will also assign the total_count to the total-items directive provided by dirPagination. Remember dir-paginate will use this number as reference to setup your pagination links.
<tr dir-paginate=”user in data.users|itemsPerPage:data.itemsPerPage” total-items=”data.total_count”>
Next we will add the pagination links using the dir-pagination-controls directive, which is also provided by dirPagination.
<dir-pagination-controls
max-size="8"
direction-links="true"
boundary-links="true"
on-page-change="data.getData(newPageNumber)">
</dir-pagination-controls>
The on-page-change directive is the key here, it takes in a callback function which is triggered on every page change. We will use this to call our vm.getdata(pageno) function. This will again make a request to the server with the new page number and our API will return the data for the next page.
- Also See: Search Sort Pagination in AngularJS
Don’t forget to declare your ng-app and ng-controller ;). Take a look at our complete markup.
<!doctype html>
<html lang="en" ng-app="angularTable">
<head>
<meta charset="utf-8">
<title>Server Side Pagination in Angular js</title>
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/bootstrap-theme.min.css">
<link rel="stylesheet" type="text/css" href="css/styles.css">
</head>
<body>
<div role="main" class="container theme-showcase">
<div class="" style="margin-top:90px;">
<div class="col-lg-8">
<div class="page-header">
<h2 id="tables">Server Side pagination in Angular js</h2>
</div>
<div class="bs-component" ng-controller="listdata as data">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Id</th>
<th>First Name</th>
<th>Last Name</th>
<th>Full Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr ng-show="data.users.length <= 0"><td colspan="5" style="text-align:center;">Loading new data!!</td></tr>
<tr dir-paginate="user in data.users|itemsPerPage:data.itemsPerPage" total-items="data.total_count">
<td>{{user.index}}</td>
<td>{{user.name}}</td>
<td>{{user.surname}}</td>
<td>{{user.fullname}}</td>
<td>{{user.email}}</td>
</tr>
</tbody>
</table>
<dir-pagination-controls
max-size="8"
direction-links="true"
boundary-links="true"
on-page-change="data.getData(newPageNumber)" >
</dir-pagination-controls>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.1/angular.js"></script>
<script src="lib/dirPagination.js"></script>
<script src="app/app.js"></script>
</body>
</html>
ng-controller="listdata as data" is from the ControllerAs syntax. This was it for this application, you can explore more and check out more options provided by dirPaginate here.
Â
Conclusion
In this article, we saw how we can easily implement Server Side Pagination in Angular Applications. This type of pagination is usually required when you have a large data set. It reduces loading time and also makes your DOM much lighter.
thanks a lot.
for .net user like me it is easy to used Entity framework in server side to avoid erroneous code in SQL statement.
You are welcome, yes, back-end implementation will depend on the technology used.
Hello ,
Last page is displayed blank . Could you please take a look.
Hi, I just checked it in the demo, seems fine.
pagination directive: the pagination controls cannot be used without the corresponding pagination directive.
Ofcourse!
while iam running this code iam getting the error like this:XMLHttpRequest cannot load http://code.ciphertrick.com/api/list/page/10/1. The ‘Access-Control-Allow-Origin’ header contains multiple values ‘*, *.ciphertrick.com’, but only one is allowed. Origin ‘http://localhost’ is therefore not allowed access.can u help me..
Hi Mahesh,
Api which you are trying to access is not allowed from origin. that’s why you getting that error.
Either you have to make another one or else you can use some dummy json data.
Thanks.
if i take any dummy json file its showing like this:angular.js:8113 GET http://localhost/json/mock.txt10/1 404 (Not Found)
If you ever get similar error it’s because of CORS(Cross-Origin Resource Sharing) the web service does not allow request from your origin.
Please use CORS tool/plugin to route your request through a different origin.
If using chrome browser use below linked extension.
https://chrome.google.com/webstore/search/Allow-Control-Allow-Origin
its really awesome bro 🙂 keep rockinggg
Fantastic tutorial, really helped me grasp what is required to achieve server side pagination!
Glad it helped!
What about Server Side Searching and Sorting?
No big deal, just send the search query in the request and construct the required query and return the data. Similar for sort.
Do you have a simple example code for filter?
I am developing an e-commerce site, basically a product grid where you can filter and paginate. For example filter buttons like:
Big ones
Small ones
Example url: “http://my-site.com/products.json?size=small
(Great article, many thanks in advance)
These articles might help you, “Learn to build a custom filter” and “Search Sort Pagination in AngularJS“.
Many thanks , but I was asking for a server-side mode to filter, sort and paginate by JSON. I have been implementing your “server-side pagination” and it works fine!, but I am not expert to add filters and sort mode.
Hello, its possible refresh or update dirpagination?, I have a problem after not found items not show records or paging.
i use input filter by scrope.filter and exec again vm.getData()
Excellent article !!
Glad you loved it!
please upload the video for server side pagination in angular js
Thanks for your inputs ashok, we will put that into our list of todos.
can i check that server side pagination in angularjs video
I have a two lists to paginate in one page. It is possible with this logic?
Yes, read about pagination-id, in dir-pagination documentation.
I am sure that my service is returning the valu e in JSON format and it worked with the client side scripting too.
But here , how can i make sure vm.users has the value .
My chrome do even show any error , post excution of the query i am getting blank page .
why there is no post method to send the pageno record no ?
————————————————for ORGIn Error
Access-Control-Allow-Origin * at Server header
Ok !! sorry !! your code is so perfect ..!!
I am so noob !! .. I was using web service and data was not as the api data format.
i got the o/p .
thanks and a lot for beautiful tutorial ..!!
You so smart !!! so quickly and nicely done !!
Keep it up and keep sharing !!
sharing is caring !! TC!!
Dear Rahil Sheikh, can you please share server side code of MySQL API,
it’s not working on localhost, i could not get values from path,
So i’ve been looking at various versions of builds using the dirPagination.js file and i’m noticing something….
the pagination functions of getCurrentPage and setCurrentPage fire multiple times on page load, and on page change and it makes no difference if it’s a client Side paging, or server side Paging, or XHR paging….
it fires multiple times…
this script needs to be seriously refactored because it is really uncool to watch page flashing because it’s loading multiple times…
This should not happen, if you are using multiple pagination on same page make sure you are providing a pagination-id.
Try tweaking the demo code and test.
If you are facing this issue without any solution, email me the src code if possible, I’ll look into it.
How are you 🙂
I’ve been using this more or less and it was working properly however I want this to be dynamic. So I’m compiling the HTML rather than using partials and injecting the compiled html into the page.
Every page is using the same tableService to create the table, so I need to be able to access the dirPagination.js script functions directly. I’ve managed everything except dealing with the controller. It’s connected but nothing works.
The only other option I have is to treat this as deprecated and force a page reload each time the itemsPerPage is changed and the page is changed, which is rather silly within an angular application.
Loading the entire collection was the way I initially started it but with the collections ranging from 10,000 to 1,000,000 this isn’t efficient.
I think that this script is useful for simple things but not really for enterprise ERP systems.
Any help would be appreciated.
It’s very nice tutorial. Tank you save my day :).
Thanks a lot. Amazing tutorial!
im showing 10 records per page and it showing as well but the pagination controls are not showing.
You may have missed including the “dir-pagination-controls” directive.
my pagination control doesn’t appear even if i use the directive
Make sure you have included pagination-controls directive
Hi Rahil Gr8 work and thanks for above the concept written by you it worked very easily without much changes. Now go to one step ahead can you please how to add Filter with each colum ?
You mean, search for each individual column?
Yes Rahil that what i am looking also it should be server side not client side ,same for Sorting as well. Client side searching/sorting i did with help of your code.
Also how to add Sorting as well.
Thanks & regards
CORS header ‘Access-Control-Allow-Origin’ does not match
This web service was used for demo purpose, access to it is blocked. You will have to make you own Web service.
Hi ,
I have one issue with controller:
XMLHttpRequest cannot load http://code.ciphertrick.com/api/list/page/10/1. The ‘Access-Control-Allow-Origin’ header contains multiple values ‘*, *.ciphertrick.com’, but only one is allowed. Origin ‘http://localhost:3000’ is therefore not allowed access.
Hi laxman,
This web service was used for demo purpose, access to it is blocked. You will have to make you own Web service.
hai rahil….
i have a problem,i have 10 records in responce variable and i am trying to display 5 records for each page by using pagination and giving index position to each record,when i was click to go next page in pagination the index position for 6th record is displaying as 1st record insted of 6th number….i need it’s display as 6th and 7th continuously….please give me a solution.
Thanks a lot. was simple and easy to use.
Hi sir,
It is good work. I tried with this example and try to change the number of items per page by using text box. It loads properly but there is one small issue the page number not get updated. for example initially i said the page number 10 and navigate to 2nd page and change the page size is 5 then it should move to 1st page. Can you please help on it.
Hello dude, was sucessfull this pagination in my web application, but the menu class “pagination” was not applicated, i would like to know what i missed or what can i do for my web app have a menu or if i can have a contact from someone that can help me i would be grateful!
Hi Sahil,
Could you share how implement new angular2
I’ll come up with that soon, stay tuned.
Hi, this is very useful to me. But my case is I want to do load given number of items when i scroll the same page. How can i modify this on my case. ?
Hi there,
First of all thanks about your article, but the demo seems not working !!!
could you please check it out.
thanks
Best regards
Yes, you are right. It might have stopped working when we moved to https. We’ll fix it soon. Thanks.
Hi rahil i am using this in angularjs. So i am getting 200 objects but pagination is not showing may i know any thing problem.