Angular2 Pagination Component with Bootstrap

I recently started learning Angular2 and I am loving it.  This article describes how to create a basic pagination component using bootstrap pagination.

The component is quite simple, it takes params (Input params) like current page no, total pages and generates the Html to display the pagination. It has Event Emitter as output which throws out the page number that user clicks to parent component and the parent can handle getting the next page data using REST or redirect to next page. For our tutorial, I will create a parent component that will receive the clicked page number from pagination component and get that’s page data using REST and update itself.

So let’s begin.

We will be using following tools for this tutorial, so install them if you don’t have already.

  1. Visual Code
  2. Node js
  3. Install angular-cli using npm ( Pretty cool command line tool for Angular)

We will be using angular-cli throughout the tutorial.

Create new Angular project using angular-cli:

Open your Visual Code.  Do Ctrl + ` to open up a terminal. Go to the folder where you want to create your project.

use “ng new pagination” command to create a new project.  Angular-cli will create the required files and proper structure for the project for you. Helpful isn’t it? It might take a while for npm to install required packages so bear with it.

create new project using angular-cli

ng new PROJECTNAME

Once finished, Open the newly created folder in Visual Code. You should see a structure similar to below:

Angular2 Project structure

Angular2 Project structure

I am not going to go into very detail explanation about the structure here but the main folder we will be working with will be “src”.

Generate Pagination component

Open up a terminal in Visual Code and run the following command:

ng generate component pagination

It will generate a new component and add the required files for it.

generate new component

ng generate component pagination

Pagination Component

Now let’s start with actually coding. This component will be received the current page, total pages, URL and name of the query parameter that indicates the page. We could define each of these as a separate parameter to our pagination component or we can bundle them together. We will go with later option.

We will add below class to out pagination.component.ts file.

export class PaginationData {
  currentPage: number;
  totalPages: number;
  baseUrl: string;
  pageQueryStringName: string;
  constructor(currentPage: number, totalPages: number, baseUrl: string, pageQueryStringName: string) {
    this.currentPage = currentPage;
    this.totalPages = totalPages;
    this.baseUrl = baseUrl;
    this.pageQueryStringName = pageQueryStringName;
  }
}

We will have an instance of that class as an input to our pagination component.

Here is the full code for the pagination Component. I will explain the section one by one:

 

import { Component, OnInit, Input, OnChanges, SimpleChanges, Output, EventEmitter } from '@angular/core';

export class PaginationData {
  currentPage: number;
  totalPages: number;
  baseUrl: string;
  pageQueryStringName: string;
  constructor(currentPage: number, totalPages: number, baseUrl: string, pageQueryStringName: string) {
    this.currentPage = currentPage;
    this.totalPages = totalPages;
    this.baseUrl = baseUrl;
    this.pageQueryStringName = pageQueryStringName;
  }
}

@Component({
  selector: 'app-pagination',
  templateUrl: './pagination.component.html',
})

export class PaginationComponent implements OnChanges {
  @Input() paginationData: PaginationData;
  @Output() outputPage: EventEmitter<number> = new EventEmitter<number>();
  pageArray: Array<number>;
  nextPage: number;
  prePage: number;
  nextPageUrl: string;
  prePageUrl: string;
  constructor() {
  }

  ngOnChanges(changes: SimpleChanges) {
    if (this.paginationData) {
      this.pageArray = new Array<number>();
      for (let i = 1; i <= this.paginationData.totalPages; i++) {
        this.pageArray.push(i);
      }

      this.nextPage = (this.paginationData.currentPage) + 1;
      this.prePage = (this.paginationData.currentPage) - 1;
      this.nextPageUrl = this.getNextPageUrl();
      this.prePageUrl = this.getPrePageUrl();
    }
  }
  getPageUrl(page: number): string {
    return this.paginationData.baseUrl + `?${this.paginationData.pageQueryStringName}=` + page;
  }

  private getPrePageUrl(): string {
    if (this.prePage <= 0) { return ''; } return this.paginationData.baseUrl + `?${this.paginationData.pageQueryStringName}=` + (this.prePage); } private getNextPageUrl(): string { if (this.nextPage > this.paginationData.totalPages) {
      return '';
    }
    return this.paginationData.baseUrl + `?${this.paginationData.pageQueryStringName}=` + (this.nextPage);
  }

  pageLinkClick(page: number) {
    if (page > 0 && page <= this.paginationData.totalPages) {
      this.outputPage.next(page);
    }
  }


}

Notice that I removed the styleUrl from Component annotation as we will be using Bootstrap CSS.

Notice that out component implements onChanges interface from Angular2.

export class PaginationComponent implements OnChanges

What it means that everytime Input parameters are changed from the parent it will call ngOnChanges on child component. The method takes an argument of type SimpleChanges where you can find the changed parameters. The reason for doing it this way is because pagination component might get initialized before parent component gets it data from API ( or somewhere else). What we will do it, we will create a new paginationData when the data has finished loading on parent component and thus calling ngOnChanges on pagination component with proper paginationData.

Pagination Component Output parameter:

Notice that the output parameter from Pagination Component is type of EventEmitter<number>.  What will happen is whenever user clicks on any page link on our pagination component we will emit that page number via our output parameter to parent component.

@Output() outputPage: EventEmitter<number> = new EventEmitter<number>();

We will call below code on page link click :

pageLinkClick(page: number) {
    if (page > 0 && page <= this.paginationData.totalPages) {
      this.outputPage.next(page);
    }
  }

Notice the “.next(page)“.

The rest of the code is easy to digest.

Let’s dive into Html of pagination component.

Template for Pagination Component:

There is not much to explain here. If you are familiar with basic of Angular2 then you will understand it right away.


<div class="text-center">


<nav aria-label="Page navigation">


<ul class="pagination pagination-lg">

      <!--Previous Link-->


<li [class.disabled]="prePageUrl == ''">
        <a aria-label="Previous" (click)="pageLinkClick(prePage)">
        <span aria-hidden="true">&laquo;</span>
      </a>
      </li>



      <!--Page Links-->


<li *ngFor="let p of pageArray" [class.active]="paginationData.currentPage == p">
        <a (click)="pageLinkClick(p)">{{p}}</a>
      </li>



      <!--Next Link-->


<li [class.disabled]="nextPageUrl == ''">
        <a aria-label="Next" (click)="pageLinkClick(nextPage)">
        <span aria-hidden="true">&raquo;</span>
      </a>
      </li>


    </ul>


  </nav>


</div>


 

Calling Pagination Component from parent component:

<app-pagination [paginationData]="paginationData" (outputPage)="goToPage($event)">
</app-pagination>

goToPage is the function defined on parent component to handle the event emitter from the pagination component. $event will out page number emitted from pagination component.

 

Leave a Reply

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