Angular and Tailwind's CSS use to create Pagination

Published on 2025-04-17

Blog Thumbnail
Build clean, responsive pagination components using Angular and Tailwind CSS. Learn how to combine Angular's logic with Tailwind's utility classes for fast styling. Streamline navigation in your apps with a modern, customizable pagination UI.

Prerequisites:

  • Node

  • Angular

  • Tailwind’s CSS

Steps:

Step 1: Install Node.js

Before we create React App we need to install node.js.

if you already installed node.js please ignore this step 1 and go to step 2.

Step 2: Install Angular and create project

 npm install -g @angular/cli
  • If you have already installed angular skip and create a project

ng new my-pagination-app --routing=true --standalone=false --style=scss
  • standalone=false is the module file created default.

  • Run the above command following question show enter select N and enter

Step 3: Install Tailwind’s CSS

  • Open your project and run the following command

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init
  • install tailwindcss via npm, and then run the init command to generate a tailwind.config.js file

  • Configure for template paths

tailwind.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ["./src/**/*.{html,ts}",],
  theme: {
    extend: {},
  },
  plugins: [],
}
  • Add the paths to all of your template files in your tailwind.config.js file.

  • Add the Tailwind directives to your CSS

styles.css

@tailwind base;
@tailwind components;
@tailwind utilities;

Step 4:

  • generate page count in page onload using ngOnInit

  • ngOnInit is the page initially called

app.component.ts

userInfo=
    [
      {
        "id": "677e4dd23e842eb5c98c14d9",
        "isActive": false,
        "name": "Cassandra Burnett",
        "gender": "female",
        "email": "cassandraburnett@dancerity.com"
      },
      {
        "id": "677e4e32e3798bf53bcbdfb8",
        "isActive": true,
        "name": "Salazar Hunt",
        "gender": "male",
        "email": "salazarhunt@dancerity.com"
      },
      {
        "id": "677e4e32b94a191800aa3653",
        "isActive": true,
        "name": "Samantha Stevenson",
        "gender": "female",
        "email": "samanthastevenson@dancerity.com"
      },
      {
        "id": "677e4e32a25bae18356d5322",
        "isActive": true,
        "name": "Beverley Curry",
        "gender": "female",
        "email": "beverleycurry@dancerity.com"
      },
      {
        "id": "677e4e320e20c94ed5000b01",
        "isActive": true,
        "name": "Nieves Petty",
        "gender": "male",
        "email": "nievespetty@dancerity.com"
      },
      {
        "id": "677e4e32b1f6a4ad5c23bd1e",
        "isActive": false,
        "name": "Andrews Manning",
        "gender": "male",
        "email": "andrewsmanning@dancerity.com"
      },
      {
        "id": "677e4e32ba2dddb082d4259a",
        "isActive": false,
        "name": "Latonya Hoover",
        "gender": "female",
        "email": "latonyahoover@dancerity.com"
      },
      {
        "id": "677e4e0f70ac33f92db30c1d",
        "isActive": false,
        "name": "Dawson Curtis",
        "gender": "male",
        "email": "dawsoncurtis@dancerity.com"
      },

      {
        "id": "677e4dd24dd5a17dbebf986a",
        "isActive": true,
        "name": "Crawford Gilmore",
        "gender": "male",
        "email": "crawfordgilmore@dancerity.com"
      },
      {
        "id": "677e4dd22b3b741355b2133a",
        "isActive": false,
        "name": "Bird Bates",
        "gender": "male",
        "email": "birdbates@dancerity.com"
      },
      {
        "id": "677e4dd2dc5a40c7322ea44f",
        "isActive": true,
        "name": "Pearl Rich",
        "gender": "female",
        "email": "pearlrich@dancerity.com"
      },
      {
        "id": "677e4dd2fe9d89f9c41d0fdb",
        "isActive": true,
        "name": "Valenzuela Stewart",
        "gender": "male",
        "email": "valenzuelastewart@dancerity.com"
      },
      {
        "id": "677e4dd29f744c6e8d782485",
        "isActive": true,
        "name": "Lindsay Harrell",
        "gender": "female",
        "email": "lindsayharrell@dancerity.com"
      },
      {
        "id": "677e4dd2a6dc5546b9a27aea",
        "isActive": true,
        "name": "Dillard Flores",
        "gender": "male",
        "email": "dillardflores@dancerity.com"
      }
    ]
  paginatedData: any[] = [];
  cuurentPage:number = 1;
  itemsPerPage: number = 5;
  totalPages: number = 0;
  pages: number[] = [];

  ngOnInit() {
    this.totalPages = Math.ceil(this.userInfo.length / this.itemsPerPage);
    this.pages = [];
    for (let i = 1; i <= this.totalPages; i++) {
      this.pages.push(i);
    }
  }

Explain:

  1. this.totalPages = Math.ceil(this.userInfo.length / this.itemsPerPage);

  • this line calculates the total number of page counts at the display

  • Math.ceil rounds a number up to the nearest integer that is greater than or equal to the given number

  • itemsPerPage is used to determine how many entries show per page

  • this.userInfo.length how many entries in the array

For example, if userInfo.length is 13 and itemsPerPage is 5, the result of 13 / 5=2.6. Applying Math.ceil() will round it returns to 3 this is the page count of this JSON.

  1.  

 for (let i = 1; i <= this.totalPages; i++) {this.pages.push(i)}
  • iterates totalpages increase count and push pages array

  • For Example, if totalPages is 5 pages array is finally [1,2,3,4,5]

 updatePagination() {
    const startIndex = (this.currentPage - 1) * this.itemsPerPage;
    const endIndex = startIndex + this.itemsPerPage;
    this.paginatedData = this.dataset.slice(startIndex, endIndex);
  }

Explain:

  1. this.paginatedData = this.dataset.slice(startIndex, endIndex);

  • startIndex is the start entries

  • For example, currentPage is 0 itemsperpage is 5 0*5 = 5.

  • endIndex is end of entries.

  • For example, startIndex is 5 itemsperpage is 5 5+5 = 10

2.

this.paginatedData = this.dataset.slice(startIndex, endIndex);
  • for example if startIndex is 5 endIndex is 10 paginatedData is 5 to 10 entries.

here is full code

app.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrl: './app.component.css'
})
export class AppComponent implements OnInit {
  dataset =
    [
      {
        "id": "677e4dd23e842eb5c98c14d9",
        "isActive": false,
        "name": "Cassandra Burnett",
        "gender": "female",
        "email": "cassandraburnett@dancerity.com"
      },
      {
        "id": "677e4e32e3798bf53bcbdfb8",
        "isActive": true,
        "name": "Salazar Hunt",
        "gender": "male",
        "email": "salazarhunt@dancerity.com"
      },
      {
        "id": "677e4e32b94a191800aa3653",
        "isActive": true,
        "name": "Samantha Stevenson",
        "gender": "female",
        "email": "samanthastevenson@dancerity.com"
      },
      {
        "id": "677e4e32a25bae18356d5322",
        "isActive": true,
        "name": "Beverley Curry",
        "gender": "female",
        "email": "beverleycurry@dancerity.com"
      },
      {
        "id": "677e4e320e20c94ed5000b01",
        "isActive": true,
        "name": "Nieves Petty",
        "gender": "male",
        "email": "nievespetty@dancerity.com"
      },
      {
        "id": "677e4e32b1f6a4ad5c23bd1e",
        "isActive": false,
        "name": "Andrews Manning",
        "gender": "male",
        "email": "andrewsmanning@dancerity.com"
      },
      {
        "id": "677e4e32ba2dddb082d4259a",
        "isActive": false,
        "name": "Latonya Hoover",
        "gender": "female",
        "email": "latonyahoover@dancerity.com"
      },
      {
        "id": "677e4e0f70ac33f92db30c1d",
        "isActive": false,
        "name": "Dawson Curtis",
        "gender": "male",
        "email": "dawsoncurtis@dancerity.com"
      },

      {
        "id": "677e4dd24dd5a17dbebf986a",
        "isActive": true,
        "name": "Crawford Gilmore",
        "gender": "male",
        "email": "crawfordgilmore@dancerity.com"
      },
      {
        "id": "677e4dd22b3b741355b2133a",
        "isActive": false,
        "name": "Bird Bates",
        "gender": "male",
        "email": "birdbates@dancerity.com"
      },
      {
        "id": "677e4dd2dc5a40c7322ea44f",
        "isActive": true,
        "name": "Pearl Rich",
        "gender": "female",
        "email": "pearlrich@dancerity.com"
      },
      {
        "id": "677e4dd2fe9d89f9c41d0fdb",
        "isActive": true,
        "name": "Valenzuela Stewart",
        "gender": "male",
        "email": "valenzuelastewart@dancerity.com"
      },
      {
        "id": "677e4dd29f744c6e8d782485",
        "isActive": true,
        "name": "Lindsay Harrell",
        "gender": "female",
        "email": "lindsayharrell@dancerity.com"
      },
      {
        "id": "677e4dd2a6dc5546b9a27aea",
        "isActive": true,
        "name": "Dillard Flores",
        "gender": "male",
        "email": "dillardflores@dancerity.com"
      }
    ]

  paginatedData: any[] = [];
  currentPage: number = 1;
  itemsPerPage: number = 5;
  totalPages: number = 0;
  pages: number[] = [];

  ngOnInit() {
    this.totalPages = Math.ceil(this.dataset.length / this.itemsPerPage);
    this.pages = [];
    for (let i = 1; i <= this.totalPages; i++) {
      this.pages.push(i);
    }
    this.updatePagination();
  }

  updatePagination() {
    const startIndex = (this.currentPage - 1) * this.itemsPerPage;
    const endIndex = startIndex + this.itemsPerPage;
    this.paginatedData = this.dataset.slice(startIndex, endIndex);
  }

  changePage(page: number) {
    if (page > 0 && page <= this.totalPages) {
      this.currentPage = page;
      this.updatePagination();
    }
  }
}

app.component.html

<div class="w-[100%] my-[40px] ">
  <table class=" relative w-[80%] mx-auto border border-gray-300 rounded-lg shadow-md min-h-[10px] max-h-full">
    <thead class="bg-gray-100 text-center font-normal text-sm">
      <tr>
        <th class="py-3">ID</th>
        <th class="py-3">IsActive</th>
        <th class="py-3">Name</th>
        <th class="py-3">Age</th>
        <th class="py-3">Gender</th>
        <th class="py-3">Email</th>
      </tr>
    </thead>
    <tbody>
      <tr *ngFor="let data of paginatedData" class="border-t hover:bg-gray-50 text-center text-sm">
        <td class="py-2">{{ data.id }}</td>
        <td class="py-2">{{ data.isActive }}</td>
        <td class="py-2">{{ data.name }}</td>
        <td class="py-2">{{ data.age }}</td>
        <td class="py-2">{{ data.gender }}</td>
        <td class="py-2">{{ data.email }}</td>
      </tr>
    </tbody>
  </table>
</div>
<div class= "absolute bottom-[100px] left-[40%] pagination-controls flex justify-center space-center my-[20px] bg-gray-200 shadow-lg w-fit  mx-auto">
  <button 
    (click)="changePage(currentPage - 1)" 
    [disabled]="currentPage === 1" 
    [class.opacity-50]="currentPage === 1" 
    class="px-4 py-2 text-sm cursor-pointer hover:bg-gray-300 disabled:opacity-50">
    Prev
  </button>
  <button 
    *ngFor="let page of pages" 
    (click)="changePage(page)" 
    [class.active]="page === currentPage" 
    class="text-sm px-2 py-1 mx-1 rounded-md hover:bg-gray-300">
    {{ page }}
  </button>
  <button 
    (click)="changePage(currentPage + 1)" 
    [disabled]="currentPage === totalPages" 
    class="px-4 py-2 text-sm cursor-pointer hover:bg-gray-300 disabled:opacity-50">
    Next
  </button>
</div>

 

 

Output: