Handle server-side pagination in an Angular application

featured_image

When pagination is performed on the backend side of a web application, we need to support this feature on the frontend. Read this post to see how you can easily handle Spring Boot Page object in an Angular app.

What we are going to build

The goal is to build a custom pagination component that accepts Spring Boot paginated response and displays it in a datatable. We will be able to control the amount of records fetched from the backend per page and which page should be displayed at the moment. After changing the number of requested elements or deleting a record we will be redirected back to the first page to avoid displaying an empty datatable.

Our example app will present a list of projects fetched from the "/api/projects" endpoint exposed by the backend API.

The finished project is available in the GitHub repository – little-pinecone/scrum_ally.

You can see the datatable created in that project on the following screenshot:

data-table-with-pagination screenshot

Architecture overview

You can see the final directory tree for the pagination part of the frontend app on the image below:

pagination-project-structure screenshot

Requirements

  • Angular CLI – a command line interface tool that generates projects, components, modules, services.
    I’m working on:
  • To see the backend part of this example web application, check out the Add pagination to a Spring Boot app post.

Handle pagination

Consume a page received from a Spring Boot app

Mirror the Page instance that will be send by the API, you can define its model in three files:

Adjust the default page size to your needs.

Add a service to handle base actions

We need a service that will update the request parameters after a user changes amount of elements per page or page number. Create the service with the following command:

We are going to start from this scaffolding:

Now, we are going to add the function that handles requesting the next page:

Furthermore, add the function for getting the previous page:

We simply increase and decrease the pageNumber variable here.

Finally, we need to handle a request that changes the amount of elements per page:

We need to show the first page when the size is being changed, therefore we need the  page.pageable.pageNumber = Pageable.FIRST_PAGE_NUMBER;  line.

All methods in this service return the pageable object.

Create the pagination component

In the terminal, use Angular CLI to generate the following component:

This component is going to utilize the functions provided by the custom-pagination.service we’ve just created to allow maneuvering between pages and change number of displayed records. Copy the following code to your custom-pagination.component.ts file:

The component requires an @Input() page: Page<any> object and emits a suitable event for every click on the pagination controls – we will handle them in a minute – but first, let’s create an html template for the component:

Let’s explain some code in this template.

We have a dropdown with hardcoded values for available page sizes:

We also took care of disabling the previous and next controls in case the given page is first or last:

In my example project build with Daemonite Material theme (based on Bootstrap) the component looks like this:
pagination-component screenshot

Include the pagination component in a component that serves the datatable

I want the pagination to be displayed under the table with the projects, so I included the component in my projects-table.component:

Here, the pagination component is given the page with projects and it can emit events notifying our projects-table.component that a user requested for a different page or changed the size of the page. The ProjectsTableComponent reacts for those events with the appropriate methods.

The projects-table.component has to request for project list every time the page is loaded:

Now, we are going to add the following methods to handle user requests made in the pagination component (answer the emitted events):

We simply modify the pageable property every time a user manipulates pagination settings. Then, the getData() method retrieves a new list of projects from the projectDataService.

Use a designated service to get data

You can find the implementation of the getPage(pageable) method from the ProjectDataService below :

We use the default sorting – by id. Check out the Handle server-side sorting in an Angular application post to see how you can implement the interactive sorting fearure.

Test the pagination

I updated the example project to Angular 8 and realised that some fixes are required. You will find them in the commit 1057f352abc.

Updated CustomPaginationService test.
Updated ProjectDataService test.

When testing the CustomPaginationService, we check whether the page number can be increased and decreased properly, and whether the change in page size redirects a user to the first page:

When testing the ProjectDataService we create a simple JSON with paginated projects and we flush it when the getPage() method is tested:

Photo by Negative Space on StockSnap

6 thoughts on “Handle server-side pagination in an Angular application

  1. Hi Can you explain how can I use it with subscription

    I have method as following

    //in app.component.ts

     

    // In app.component.ts 
    getObjects(){
    this.objectService.findUsers(this.searchParams).subscribe
                ((responseany=> {
    // do some operations here

      });
    }

    // In objectService.ts

    findObjects(searchParamssearchParams) { // This is common method which can be used without pagination too. therefore
    we dont want to define Observable here, Can you help how can we achieve
      return this.http.get(url, httpOptions);
      }

    1. Hi,

      I’m afraid that making pagination code work without pagination is outside of the scope of this article. Although I can’t help you, I encourage you to start with writing a set of unit tests. It may help you to clarify the issue and requirements. Furthermore, the tests may show you the right direction to solve this advanced use case or assist you in getting better answers on StackOverflow.

  2. Hello!

    Could you give me a light on how the server-side paging would look, I’m implementing this example on the angular but on the server I still couldn’t do it on my webapi project.

    1. Hi,

      I built the backend with Spring Boot. Therefore, I could use the PagingAndSortingRepository which does all the work for me. I described it in the How to add pagination to a Spring Boot app post and implemented it in the scrum_ally project (e.g. ProjectController::findAllForCurrentUser()). The Page<T> class I created in this post has the same structure as the default json response returned from my Spring Boot repositories that extend the PagingAndSortingRepository.

      If the framework you use to build an API already handles pagination it can save you a lot of work. Otherwise, you can find some inspiration and good practices in articles like those:

      Implementing the server side-paging is worth the work because it helps to keep performance of an API on a decent level. Even a simple usage of limit and offset parameters passed from frontend to our SQL queries is a great start.

Leave a Reply

Your email address will not be published. Required fields are marked *