Angular 16 Pagination example
Tags: angular, webdev, beginners, javascript
Published: 2023-08-05 01:13:25

In this tutorial, I will show you how to make Angular 16 Pagination example with existing API (server-side pagination) using ngx-pagination.

Related Posts:
- <a href="https://www.bezkoder.com/angular-16-crud-example/">Angular 16 CRUD example with Rest Api</a>
- <a href="https://www.bezkoder.com/angular-16-form-validation/">Angular 16 Form Validation example (Reactive Forms)</a>
- <a href="https://www.bezkoder.com/angular-16-file-upload/">Angular 16 File upload example with Progress bar</a>
- <a href="https://www.bezkoder.com/angular-16-jwt-auth/">Angular 16 JWT Authentication example with Web Api</a>

Fullstack with Node.js Express:
<a href="https://bezkoder.com/server-side-pagination-node-js-angular/">Server side Pagination with Node.js and Angular</a>

Fullstack with Spring Boot:
<a href="https://bezkoder.com/pagination-spring-boot-angular-12/">Spring Boot + Angular: Server side Pagination example</a>

<h2>Overview of Angular 16 Pagination example</h2>
One of the most important things to make a website friendly is the response time, and pagination comes for this reason. For example, this bezkoder.com website has hundreds of tutorials, and we don’t want to see all of them at once. Paging means displaying a small number of all, by a page.

Assume that we have tutorials table in database like this:

<img src="https://www.bezkoder.com/wp-content/uploads/angular-16-pagination-example-database.png" alt="angular-16-pagination-example-database" width="310" height="720" class="alignnone size-full wp-image-14889" />

Our Angular 16 app will display the result with pagination:

<img src="https://www.bezkoder.com/wp-content/uploads/angular-16-pagination-example-ngx-pagination.png" alt="angular-16-pagination-example-ngx-pagination" width="660" height="462" class="alignnone size-full wp-image-14890" />

You can change to a page with larger index:

<img src="https://www.bezkoder.com/wp-content/uploads/angular-16-pagination-example-ngx-pagination-change-page-1.png" alt="angular-16-pagination-example-change-page" width="660" height="460" class="alignnone size-full wp-image-14891" />

Or change quantity of items per page:

<img src="https://www.bezkoder.com/wp-content/uploads/angular-16-pagination-example-items-per-page.png" alt="angular-16-pagination-example-items-per-page" width="660" height="610" class="alignnone size-full wp-image-14892" />

Or paging with filter:

<img src="https://www.bezkoder.com/wp-content/uploads/angular-16-pagination-example-ngx-pagination-filter.png" alt="angular-16-pagination-example-ngx-pagination-filter" width="660" height="600" class="alignnone size-full wp-image-14893" />

The API for this Angular client can be found at one of following posts:
- <a href="https://bezkoder.com/node-js-sequelize-pagination-mysql/">Node Express Pagination with MySQL</a>
- <a href="https://bezkoder.com/node-js-pagination-postgresql/">Node Express Pagination with PostgreSQL</a>
- <a href="https://bezkoder.com/node-js-mongodb-pagination/">Node Express Pagination with MongoDB</a>
- <a href="https://bezkoder.com/spring-boot-pagination-filter-jpa-pageable/">Spring Boot Pagination & Filter example | Spring JPA, Pageable</a>
- <a href="https://bezkoder.com/spring-boot-mongodb-pagination/">Spring Boot MongoDB Pagination example with Spring Data</a>

These Servers will exports API for pagination (with/without filter), here are some url samples:
<ul>
	<li><code>/api/tutorials?page=1&size=5</code></li>
	<li><code>/api/tutorials?size=5</code>: using default value for page</li>
	<li><code>/api/tutorials?page=1</code>: using default value for size</li>
	<li><code>/api/tutorials?title=data&page=1&size=3</code>: pagination & filter by title containing 'data'</li>
</ul>

This is structure of the response (server-side pagination) for the HTTP GET request:
```json
{
    "totalItems": 8,
    "tutorials": [...],
    "totalPages": 3,
    "currentPage": 1
}
```

This is a kind of server-side paging, where the server sends just a single page at a time. <code>ngx-pagination</code> supports this scenario, so We actually only need to use <code>tutorials</code> and <code>totalItems</code> when working with this library.

<h2>ngx-pagination with Angular 16</h2>
<a href="https://www.npmjs.com/package/ngx-pagination">ngx-pagination</a> provides <code>NgxPaginationModule</code> for displaying pagination with numbers and responsive style.

There are 2 main things that we're gonna use: 
- <code>PaginatePipe</code>: placed at the end of an <code>ngFor</code> expression
```html
<your-element *ngFor="let item of collection | paginate: { id: 'foo',
                                                      itemsPerPage: pageSize,
                                                      currentPage: page,
                                                      totalItems: total }">...</your-element>
```
Use the <code>id</code> if you need to support more than one instance of pagination at a time.
- <code>PaginationControlsComponent</code>: a default component for displaying pagination controls
```html
<pagination-controls></pagination-controls>
```


For example, this is the default display for simple <code>pagination-controls</code> above:

<img src="https://www.bezkoder.com/wp-content/uploads/ngx-pagination-example-angular-16-pagination-controls.png" alt="ngx-pagination-example-angular-16-pagination-controls" width="500" height="60" class="alignnone size-full wp-image-14894" />

We can customize the label displayed on the "previous"/"next" link using <code>previousLabel</code>/<code>nextLabel</code>, and enable "responsive" to hide individual page links on small screens.

```html
<pagination-controls
  previousLabel="Prev"
  nextLabel="Next"
  responsive="true"
></pagination-controls>
```

<img src="https://www.bezkoder.com/wp-content/uploads/ngx-pagination-example-angular-16-customize-pagination-controls.png" alt="ngx-pagination-example-angular-16-customize-pagination-controls" width="500" height="120" class="alignnone size-full wp-image-14895" />

For handling page changes, we pass <code>handlePageChange</code> to <code>pageChange</code>.
Notice that count is <code>totalItems</code> in the API response, and <code>page</code> is the current page.

```html
<pagination-controls
  (pageChange)="handlePageChange($event)"
></pagination-controls>

<ul>
  <li
    *ngFor="let tutorial of tutorials | paginate: {
              itemsPerPage: pageSize,
              currentPage: page,
              totalItems: count
            }"
  >
    {{ tutorial.title }}
  </li>
</ul>
```

```js
@Component(...)
export class TutorialsListComponent {
  ...
  page = 1;

  handlePageChange(event) {
    this.page = event;
  }

}
```

<code>pageChange</code> is the expression invoked whenever the page changes via a click on the pagination controls. The <code>$event</code> argument will be the number of the new page.

There are more attributes that <code>ngx-pagination</code> supports:

```html
<pagination-controls  id="some_id"
                      (pageChange)="pageChanged($event)"
                      (pageBoundsCorrection)="pageChanged($event)"
                      maxSize="9"
                      directionLinks="true"
                      autoHide="true"
                      responsive="true"
                      previousLabel="Previous"
                      nextLabel="Next"
                      screenReaderPaginationLabel="Pagination"
                      screenReaderPageLabel="page"
                      screenReaderCurrentLabel="You're on page">
</pagination-controls>
```

You can find the details at: <a href="https://www.npmjs.com/package/ngx-pagination">https://www.npmjs.com/package/ngx-pagination</a>.

<h2>Technology</h2>
<ul>
	<li>Angular 16</li>
	<li>RxJS 7</li>
	<li>ngx-pagination 6</li>
</ul>

<h2>Setup Angular 16 Pagination Project</h2>
Let's open cmd and use Angular CLI to create a new Angular Project as following command:
```
ng new angular-16-pagination-example
? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? CSS
```

You can follow step by step, or get source code in this post:
<a href="https://www.bezkoder.com/angular-16-crud-example/">Angular 16 CRUD example with Web API</a>

The Angular 16 Project contains structure that we only need to add some changes (in <em>tutorials-list</em> component and <em>tutorial.service.ts</em>) to make the pagination work well.

<img src="https://www.bezkoder.com/wp-content/uploads/angular-16-pagination-example-project.png" alt="angular-16-pagination-example-project" width="270" height="660" class="alignnone size-full wp-image-14896" />

Or you can get the new Github source code at the end of this tutorial.

<h2>Setup ngx-pagination for Angular 16 Pagination example</h2>
We need to install <code>ngx-pagination</code> with command:
<code>npm install ngx-pagination</code>

Then open <em>app.module.ts</em> and import it:

```js
...
import { HttpClientModule } from '@angular/common/http';
import { NgxPaginationModule } from 'ngx-pagination';

@NgModule({
  declarations: [ ... ],
  imports: [
    ...
    NgxPaginationModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
```

<h2>Create Data Service</h2>
This service will use Angular HttpClient to send HTTP requests.

<strong>services</strong>/<em>tutorial.service.ts</em>
```js
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Tutorial } from '../models/tutorial.model';

const baseUrl = 'http://localhost:8080/api/tutorials';

@Injectable({
  providedIn: 'root'
})
export class TutorialService {

  constructor(private http: HttpClient) { }

  getAll(params: any): Observable<any> {
    return this.http.get<any>(baseUrl, { params });
  }

  // other CRUD operations
}
```

In the code above, you can see that we pass <code>params</code> object to GET method.
The <code>params</code> object will have one, two or all fields: <code>title</code>, <code>page</code>, <code>size</code>.

<h2>Create Angular 16 Component with Pagination</h2>
This component has:
<ul>
	<li>a search bar for finding Tutorials by <em>title</em>.</li>
	<li>a select element for quantity of items per page.</li>
	<li>a <code>PaginationControlsComponent</code> component</li>
	<li>a <em>tutorials</em> array displayed as a list on the left.</li>
	<li>a selected Tutorial which is shown on the right.</li>
</ul>

<img src="https://www.bezkoder.com/wp-content/uploads/angular-16-pagination-example-items-per-page.png" alt="angular-16-pagination-example-items-per-page" width="660" height="610" class="alignnone size-full wp-image-14892" />

<strong>components</strong>/<strong>tutorials-list</strong>/<em>tutorials-list.component.html</em>
```html
<div class="list row">
  <div class="col-md-8">
    <div class="input-group mb-3">
      <input
        type="text"
        class="form-control"
        placeholder="Search by title"
        [(ngModel)]="title"
      />
      <div class="input-group-append">
        <button
          class="btn btn-outline-secondary"
          type="button"
          (click)="searchTitle()"
        >
          Search
        </button>
      </div>
    </div>
  </div>

  <div class="col-md-12">
    <pagination-controls
      previousLabel="Prev"
      nextLabel="Next"
      [responsive]="true"
      (pageChange)="handlePageChange($event)"
    ></pagination-controls>
  </div>

  <div class="col-md-6">
    <h4>Tutorials List</h4>

    <ul class="list-group">
      <li
        class="list-group-item"
        *ngFor="
          let tutorial of tutorials | paginate : {
                  itemsPerPage: pageSize,
                  currentPage: page,
                  totalItems: count
                };
          let i = index
        "
        ...
      >
        {{ tutorial.title }}
      </li>
    </ul>
  </div>
  ...

  <div class="mt-3">
    ...

    Items per Page:
    <select (change)="handlePageSizeChange($event)">
      <option *ngFor="let size of pageSizes" [ngValue]="size">
        {{ size }}
      </option>
    </select>
  </div>
</div>
```

We will have following variables:
- search and display Tutorials:
<ul>
	<li><code>title</code></li>
	<li><code>tutorials</code></li>
	<li><code>currentTutorial</code> and <code>currentIndex</code></li>
</ul>
- pagination:
<ul>
	<li><code>page</code>: current page</li>
	<li><code>count</code>: total pages</li>
	<li><code>pageSize</code>: number of items in each page</li>
</ul>

For pagination, we're gonna use <code>TutorialService.getAll()</code> methods.

<strong>components</strong>/<strong>tutorials-list</strong>/<em>tutorials-list.component.ts</em>
```js
import { Component, OnInit } from '@angular/core';
import { Tutorial } from 'src/app/models/tutorial.model';
import { TutorialService } from 'src/app/services/tutorial.service';

@Component({
  selector: 'app-tutorials-list',
  templateUrl: './tutorials-list.component.html',
  styleUrls: ['./tutorials-list.component.css']
})
export class TutorialsListComponent implements OnInit {

  tutorials: Tutorial[] = [];
  currentTutorial: Tutorial = {};
  currentIndex = -1;
  title = '';

  page = 1;
  count = 0;
  pageSize = 3;
  pageSizes = [3, 6, 9];

  constructor(private tutorialService: TutorialService) { }

  ngOnInit(): void {
    this.retrieveTutorials();
  }

  getRequestParams(searchTitle: string, page: number, pageSize: number): any {
    let params: any = {};

    if (searchTitle) {
      params[`title`] = searchTitle;
    }

    if (page) {
      params[`page`] = page - 1;
    }

    if (pageSize) {
      params[`size`] = pageSize;
    }

    return params;
  }

  retrieveTutorials(): void {
    const params = this.getRequestParams(this.title, this.page, this.pageSize);

    this.tutorialService.getAll(params)
    .subscribe(
      response => {
        const { tutorials, totalItems } = response;
        this.tutorials = tutorials;
        this.count = totalItems;
        console.log(response);
      },
      error => {
        console.log(error);
      });
  }

  handlePageChange(event: number): void {
    this.page = event;
    this.retrieveTutorials();
  }

  handlePageSizeChange(event: any): void {
    this.pageSize = event.target.value;
    this.page = 1;
    this.retrieveTutorials();
  }

  ...

  searchTitle(): void {
    this.page = 1;
    this.retrieveTutorials();
  }
}
```
Let me explain some lines of code.

In the <code>retrieveTutorials()</code> method:
- We get <code>title</code>, <code>page</code>, <code>pageSize</code> value and transform them into <code>params</code> object:
```json
{
    "title": searchTitle,
    "page": page - 1,
    "size": pageSize
}
```

- We use <code>tutorials</code> and <code>totalItems</code> as <code>count</code> value from the response data:
```json
{
    "totalItems": 8,
    "tutorials": [...],
    "totalPages": 3,
    "currentPage": 1
}
```

<code>handlePageChange()</code> and <code>handlePageSizeChange()</code> methods are for setting new <code>page</code> and <code>pageSize</code>, then we invoke <code>retrieveTutorials()</code> that updates the tutorials List when pagination information changes.

<h2>Run Angular 16 Pagination example</h2>
First you need to run the Server at one of following posts:
<ul>
	<li><a href="https://www.bezkoder.com/node-js-sequelize-pagination-mysql/">Node Express Pagination with MySQL</a></li>
	<li><a href="https://www.bezkoder.com/node-js-pagination-postgresql/">Node Express Pagination with PostgreSQL</a></li>
	<li><a href="https://www.bezkoder.com/node-js-mongodb-pagination/">Node Express Pagination with MongoDB</a></li>
	<li><a href="https://www.bezkoder.com/spring-boot-pagination-filter-jpa-pageable/">Spring Boot Pagination & Filter example | Spring JPA, Pageable</a></li>
	<li><a href="https://www.bezkoder.com/spring-boot-mongodb-pagination/">Spring Boot MongoDB Pagination example with Spring Data</a></li>
</ul>

Then you can run our App with command: <code>ng serve --port 8081</code>.
If the process is successful, open Browser with Url: <code>http://localhost:8081/</code> and check it.

<h2>Conclusion</h2>
Today we've built a Angular 16 Pagination example that consume API (server-side pagination) successfully with <code>ngx-pagination</code>. I hope you apply it in your project at ease.

Happy learning, see you again!

<h2>Source Code</h2>
You can find the complete source code for this tutorial on <a href="https://github.com/bezkoder/angular-16-pagination-example">Github</a>.

<h2>Further Reading</h2>
<ul>
	<li><a href="https://www.npmjs.com/package/ngx-pagination">https://www.npmjs.com/package/ngx-pagination</a></li>
	<li><a href="https://angular.io/guide/http">Angular HttpClient</a></li>
</ul>

Fullstack with Node.js Express:
<a href="https://www.bezkoder.com/server-side-pagination-node-js-angular/">Server side Pagination with Node.js and Angular</a>

Fullstack with Spring Boot:
<a href="https://www.bezkoder.com/pagination-spring-boot-angular-12/">Spring Boot + Angular: Server side Pagination example</a>