File

src/components/sq-pagination/sq-pagination.component.ts

Description

Represents a pagination component for navigating through pages.

Look the link about the component in original framework and the appearance

See https://css.squidit.com.br/components/pagination

Example :
<sq-pagination [currentPage]="currentPage" [totalPages]="totalPages" [showPages]="5" (pageChange)="onPageChange($event)"></sq-pagination>

Implements

OnInit OnChanges OnDestroy

Metadata

Index

Properties
Methods
Inputs
Outputs

Constructor

constructor(route: ActivatedRoute, router: Router, getWindow: GetWindow, ngZone: NgZone)

Initializes a new instance of the SqPaginationComponent class.

Parameters :
Name Type Optional Description
route ActivatedRoute No
  • The ActivatedRoute service for retrieving route information.
router Router No
  • The Router service for programmatic navigation.
getWindow GetWindow No
  • The GetWindow service for accessing the window object.
ngZone NgZone No
  • The NgZone service for running code outside Angular's zone.

Inputs

currentPage
Type : number
Default value : 1

The current page number.

customClass
Type : string
Default value : ''

A custom CSS class for styling the component.

showPages
Type : number
Default value : 5

The number of page links to show in the pagination control.

totalPages
Type : number
Default value : 1

The total number of pages.

useQueryString
Type : boolean
Default value : false

Indicates whether to use query string parameters for page navigation.

Outputs

pageChange
Type : EventEmitter<number>

Emits an event when the current page is changed.

Methods

calculateHalf
calculateHalf()

Calculates half of the showPages setting for determining which pages to display.

Returns : any
createOrDestroyQueryObservable
createOrDestroyQueryObservable()

Creates or destroys the query parameter observable based on the useQueryString input.

Returns : void
destroyQueryObservable
destroyQueryObservable()

Destroys the query parameter observable and removes the 'page' query parameter from the URL.

Returns : void
handlePageChange
handlePageChange(newPage: number)

Handles a page change event and updates the page number.

Parameters :
Name Type Optional Description
newPage number No
  • The new page number.
Returns : void
mountQueryObservable
mountQueryObservable()

Mounts the query parameter observable to track page changes in the URL query string.

Returns : void
ngOnChanges
ngOnChanges(changes: SimpleChanges)

Responds to changes in input properties.

Parameters :
Name Type Optional Description
changes SimpleChanges No
  • The changes in input properties.
Returns : void
ngOnDestroy
ngOnDestroy()

Cleans up resources when the component is destroyed.

Returns : void
ngOnInit
ngOnInit()

Initializes the component.

Returns : void

Properties

canShow
Default value : useMemo((actualPage: number) => { const half = this.calculateHalf(); return actualPage === this.page || (actualPage >= this.page - half && actualPage <= this.page + half); })

Checks if a page number should be displayed based on the current page and showPages setting.

Parameters :
Name Description
actualPage
  • The page number to check.
Public getWindow
Type : GetWindow
- The GetWindow service for accessing the window object.
page
Default value : this.currentPage

The current page number.

pages
Default value : Array.from({ length: this.totalPages }, (_, i) => i + 1)

An array of page numbers to display in the pagination control.

routeObservable
Type : Subscription

A subscription to the route query parameters.

showDotMax
Default value : useMemo((actualPage: number) => { const half = this.calculateHalf(); return actualPage + half < this.totalPages; })

Checks if the maximum page number dot should be shown.

Parameters :
Name Description
actualPage
  • The page number to check.
showDotMin
Default value : useMemo((actualPage: number) => { const half = this.calculateHalf(); return actualPage - half > 1; })

Checks if the minimum page number dot should be shown.

Parameters :
Name Description
actualPage
  • The page number to check.
import {
  Component,
  EventEmitter,
  Input,
  NgZone,
  OnChanges,
  OnDestroy,
  OnInit,
  Output,
  SimpleChanges,
} from '@angular/core';
import { NgClass } from '@angular/common';
import { useMemo } from '../../helpers/memo.helper';
import { ActivatedRoute, Router } from '@angular/router';
import { Subscription } from 'rxjs';
import { GetWindow } from '../../helpers/window.helper';

/**
 * Represents a pagination component for navigating through pages.
 *
 * Look the link about the component in original framework and the appearance
 *
 * @see {@link https://css.squidit.com.br/components/pagination}
 *
 *  <div class='my-3' >
 *    <ul class="pagination" style='padding: 0; margin: 0;'>
 *      <li class="disabled">
 *        <a>
 *          <i class="fas fa-chevron-left"></i>
 *        </a>
 *      </li>
 *      <li>
 *        <a>1</a>
 *      </li>
 *      <li class='active'>
 *        <a>2</a>
 *      </li>
 *      <li>
 *        <a>3</a>
 *      </li>
 *      <li>
 *        <a>
 *          <i class="fas fa-chevron-right"></i>
 *        </a>
 *      </li>
 *    </ul>
 *  </div>
 *
 * @example
 * <sq-pagination [currentPage]="currentPage" [totalPages]="totalPages" [showPages]="5" (pageChange)="onPageChange($event)"></sq-pagination>
 *
 * @implements {OnInit, OnChanges, OnDestroy}
 */
@Component({
  selector: 'sq-pagination',
  templateUrl: './sq-pagination.component.html',
  styleUrls: ['./sq-pagination.component.scss'],
  standalone: true,
  imports: [NgClass],
})
export class SqPaginationComponent implements OnInit, OnChanges, OnDestroy {
  /**
   * A custom CSS class for styling the component.
   */
  @Input() customClass = '';

  /**
   * The current page number.
   */
  @Input() currentPage = 1;

  /**
   * The total number of pages.
   */
  @Input() totalPages = 1;

  /**
   * The number of page links to show in the pagination control.
   */
  @Input() showPages = 5;

  /**
   * Indicates whether to use query string parameters for page navigation.
   */
  @Input() useQueryString = false;

  /**
   * Emits an event when the current page is changed.
   */
  @Output() pageChange: EventEmitter<number> = new EventEmitter<number>();

  /**
   * The current page number.
   */
  page = this.currentPage;

  /**
   * An array of page numbers to display in the pagination control.
   */
  pages = Array.from({ length: this.totalPages }, (_, i) => i + 1);

  /**
   * A subscription to the route query parameters.
   */
  routeObservable!: Subscription;

  /**
   * Initializes a new instance of the `SqPaginationComponent` class.
   * @constructor
   * @param {ActivatedRoute} route - The ActivatedRoute service for retrieving route information.
   * @param {Router} router - The Router service for programmatic navigation.
   * @param {GetWindow} getWindow - The GetWindow service for accessing the window object.
   * @param {NgZone} ngZone - The NgZone service for running code outside Angular's zone.
   */
  constructor(
    private route: ActivatedRoute,
    private router: Router,
    public getWindow: GetWindow,
    private ngZone: NgZone
  ) {}

  /**
   * Initializes the component.
   */
  ngOnInit() {
    this.createOrDestroyQueryObservable();
  }

  /**
   * Responds to changes in input properties.
   *
   * @param {SimpleChanges} changes - The changes in input properties.
   */
  ngOnChanges(changes: SimpleChanges) {
    if (changes['currentPage'] && changes['currentPage'].currentValue !== changes['currentPage'].previousValue) {
      this.page = this.currentPage;
    }
    if (changes['totalPages'] && changes['totalPages'].currentValue !== changes['totalPages'].previousValue) {
      this.pages = Array.from({ length: this.totalPages }, (_, i) => i + 1);
    }
    if (
      changes['useQueryString'] &&
      changes['useQueryString'].currentValue !== changes['useQueryString'].previousValue
    ) {
      this.createOrDestroyQueryObservable();
    }
  }

  /**
   * Cleans up resources when the component is destroyed.
   */
  ngOnDestroy() {
    this.destroyQueryObservable();
  }

  /**
   * Creates or destroys the query parameter observable based on the `useQueryString` input.
   */
  createOrDestroyQueryObservable() {
    if (this.useQueryString) {
      this.mountQueryObservable();
    } else {
      this.destroyQueryObservable();
    }
  }

  /**
   * Mounts the query parameter observable to track page changes in the URL query string.
   */
  mountQueryObservable() {
    this.routeObservable = this.route.queryParams.subscribe(search => {
      const searchParams = new URLSearchParams(search);
      const newPageQuery = parseInt(searchParams.get('page') ?? '1', 10);
      if (newPageQuery !== this.page) {
        this.page = newPageQuery;
      }
    });
  }

  /**
   * Destroys the query parameter observable and removes the 'page' query parameter from the URL.
   */
  destroyQueryObservable() {
    const searchParams = new URLSearchParams(this.getWindow.window()?.location.search);
    searchParams.delete('page');
    this.ngZone.run(() => {
      this.router.navigate([], { relativeTo: this.route, queryParams: { page: null }, queryParamsHandling: 'merge' });
    });
    this.routeObservable?.unsubscribe();
  }

  /**
   * Checks if a page number should be displayed based on the current page and showPages setting.
   *
   * @param {number} actualPage - The page number to check.
   * @returns {boolean} - `true` if the page should be shown, otherwise `false`.
   */
  canShow = useMemo((actualPage: number) => {
    const half = this.calculateHalf();
    return actualPage === this.page || (actualPage >= this.page - half && actualPage <= this.page + half);
  });

  /**
   * Checks if the maximum page number dot should be shown.
   *
   * @param {number} actualPage - The page number to check.
   * @returns {boolean} - `true` if the dot should be shown, otherwise `false`.
   */
  showDotMax = useMemo((actualPage: number) => {
    const half = this.calculateHalf();
    return actualPage + half < this.totalPages;
  });

  /**
   * Checks if the minimum page number dot should be shown.
   *
   * @param {number} actualPage - The page number to check.
   * @returns {boolean} - `true` if the dot should be shown, otherwise `false`.
   */
  showDotMin = useMemo((actualPage: number) => {
    const half = this.calculateHalf();
    return actualPage - half > 1;
  });

  /**
   * Calculates half of the `showPages` setting for determining which pages to display.
   */
  calculateHalf() {
    return Math.floor(this.showPages / 2);
  }

  /**
   * Handles a page change event and updates the page number.
   *
   * @param {number} newPage - The new page number.
   */
  handlePageChange(newPage: number) {
    if (newPage < 1 || newPage > this.totalPages) {
      return;
    }
    if (this.useQueryString) {
      const searchParams = new URLSearchParams(this.getWindow.window()?.location.search);
      searchParams.set('page', newPage.toString());
      this.ngZone.run(() => {
        this.router.navigate([], {
          relativeTo: this.route,
          queryParams: { page: newPage },
          queryParamsHandling: 'merge',
        });
      });
    }

    this.page = newPage;
    this.pageChange.emit(newPage);
  }
}
<div class="pagination-wrapper {{ customClass }}">
  <ul class="pagination">
    <li
      class="page-item"
      [ngClass]="{
        disabled: page === 1,
      }"
    >
      <button (click)="handlePageChange(page - 1)">
        <i class="fa-solid fa-chevrons-left"></i>
      </button>
    </li>

    @if (showDotMin(page)) {
      <li class="disabled">
        <button>
          <i class="fa-solid fa-ellipsis"></i>
        </button>
      </li>
    }

    @for (p of pages; track p) {
      @if (canShow(p)) {
        <li
          [ngClass]="{
            active: page === p,
          }"
        >
          <button (click)="handlePageChange(p)">
            {{ p }}
          </button>
        </li>
      }
    }

    @if (showDotMax(page)) {
      <li class="disabled">
        <button>
          <i class="fa-solid fa-ellipsis"></i>
        </button>
      </li>
    }

    <li
      class="page-item"
      [ngClass]="{
        disabled: page >= totalPages,
      }"
    >
      <button (click)="handlePageChange(page + 1)">
        <i class="fa-solid fa-chevrons-right"></i>
      </button>
    </li>
  </ul>
</div>

./sq-pagination.component.scss

.pagination-wrapper {
  width: 100%;
  text-align: center;
}
.pagination li.active {
  color: var(--primary_color);
}
:host {
  display: inline-block;
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""