Angular pagination component

Pagination is a usefull component that helps you display page numbers for your data collections. I ended up building my own simple component after spending too much time trying to customize already existing ones added in the project by my coleagues. I wanted something simple, to do only what I need, in a clear way.

Let’s suppose we already have a working project for this example, I am using the default angular template available in Visual Studio for this post.

Create a new component

First step is to create a new component. I am generating a new one using the Angular CLI commands:

PS C:\Users\scb\Desktop\scb.pagination> ng g c pagination
// pagination.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'scb-pagination',
  templateUrl: './pagination.component.html',
  styleUrls: ['./pagination.component.css']
})
export class SCBPaginationComponent {
  constructor() {}
}

Required inputs / output

To properly buid the pagination behaviour we need at least two input parameters and an output event.

Input parameters:

  • totalItems – number of items in the collection that pagination should handle
  • pageSize – number of items per page

Output events:

  • pageChange – emits events when a user clicks previus/next buttons

At this point our component can be used like this

<scb-pagination 
      [totalItems]="100"
      [pageSize]="5"
      (pageChange)="onPageChange($event)">
</scb-pagination>

HTML template

I want my component to look as simple as possible, but nice, like this:

//pagination.component.html
<ul class="pagination">
  <li>
    <a class="btn" href="#"
       (click)="first($event)"
       [ngClass]="{ 'disabled': isFirstPage }">
      <span aria-hidden="true">«</span>
    </a>
  </li>
  <li>
    <a class="btn" href="#"
       (click)="prev($event)"
       [ngClass]="{ 'disabled': isFirstPage }">
      <span aria-hidden="true">«</span>
    </a>
  </li>
  <li>
    <a>
      {{startItem}} - {{endItem}} of {{totalItems}}
    </a>
  </li>
  <li>
    <a class="btn" href="#"
       (click)="next($event)"
       [ngClass]="{ 'disabled': isLastPage }">
      <span aria-hidden="true">»</span>
    </a>
  </li>
  <li>
    <a class="btn" href="#"
       (click)="last($event)"
       [ngClass]="{ 'disabled': isLastPage }">
      <span aria-hidden="true">»</span>
    </a>
  </li>
</ul>

Typescript

//pagination.component.ts
import { Component, EventEmitter, Input, Output } from '@angular/core';

@Component({
  selector: 'scb-pagination',
  templateUrl: './pagination.component.html',
  styleUrls: ['./pagination.component.css']
})
export class SCBPaginationComponent {
  @Input() totalItems: number;
  @Input() pageSize: number;
  @Output() pageChange = new EventEmitter<number>();

  public page: number = 1;

  get startItem() {
    return ((this.page - 1) * this.pageSize) + 1;
  }

  get endItem() {
    var end = this.page * this.pageSize;
    return end < this.totalItems ? end : this.totalItems;
  }

  get isFirstPage() {
    return this.page == 1 ? true : false;
  }

  get isLastPage() {
    return this.endItem == this.totalItems ? true : false;
  }

  constructor() {
  }

  first(event) {
    event.preventDefault();
    this.page = 1;
    this.pageChange.emit(this.page);
  }

  last(event) {
    event.preventDefault();
    this.page = Math.floor(this.totalItems / this.pageSize) + 1;
    this.pageChange.emit(this.page);
  }

  next(event) {
    event.preventDefault();
    this.page += 1;
    this.pageChange.emit(this.page);
  }

  prev(event) {
    event.preventDefault();
    this.page -= 1;
    this.pageChange.emit(this.page);
  }
}

The only thing remaing now is to implement the callback function onPageChange to filter the data displayed, and to replace the hardcoded values for input parameters :-).

Be First to Comment

Leave a Reply

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