import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'; type Page = { startPage: number; currentPage: number; endPage: number; totalPages: number; pages: number[]; }; @Component({ selector: 'app-paginator', templateUrl: './paginator.component.html', styleUrls: ['./paginator.component.scss'] }) export class PaginatorComponent implements OnChanges { @Input() totalItems: number; @Input() pageSize: number; @Input() maxPages: number; @Output() pageChange: EventEmitter = new EventEmitter(); currentPage: number = 1; pages: Page; ngOnChanges(_: SimpleChanges): void { this.#paginate(); } setPage(page: number) { if(page === this.currentPage) return; this.pageChange.emit(page); this.currentPage = page; this.#paginate(); } #paginate() { const totalPages = Math.ceil(this.totalItems / this.pageSize); let startPage: number; let endPage: number; if (totalPages <= this.maxPages) { // total pages less than max so show all pages startPage = 1; endPage = totalPages; } else { // total pages more than max so calculate start and end pages const maxPagesBeforeCurrentPage = Math.floor(this.maxPages / 2); const maxPagesAfterCurrentPage = Math.ceil(this.maxPages / 2) - 1; if (this.currentPage <= maxPagesBeforeCurrentPage) { // current page near the start startPage = 1; endPage = this.maxPages; } else if (this.currentPage + maxPagesAfterCurrentPage >= totalPages) { // current page near the end startPage = totalPages - this.maxPages + 1; endPage = totalPages; } else { // current page somewhere in the middle startPage = this.currentPage - maxPagesBeforeCurrentPage; endPage = this.currentPage + maxPagesAfterCurrentPage; } } const pages = Array.from(Array((endPage + 1) - startPage).keys()).map(i => startPage + i); // return object with all pager properties required by the view this.pages = { currentPage: this.currentPage, startPage: startPage, endPage: endPage, totalPages: totalPages, pages: pages }; } }