import { CommonModule } from '@angular/common'; import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, } from '@angular/core'; import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; import { faSort, faSortDown, faSortUp, } from '@fortawesome/free-solid-svg-icons'; import { SORT } from '../../enums/sort'; import { Header } from '../../models/header'; import { Page } from '../../models/page'; import { Result } from '../../models/result'; @Component({ selector: 'fbi-table', standalone: true, imports: [CommonModule, FontAwesomeModule], templateUrl: './table.component.html', styleUrl: './table.component.scss', }) export class TableComponent implements OnChanges { @Input() data!: Result; @Output() page = new EventEmitter(); @Output() sort = new EventEmitter
(); Math = Math; faSortDown = faSortDown; faSortUp = faSortUp; faSort = faSort; SORT = SORT; pagesize: PageButton[] = []; pager: PageButton[] = []; ngOnChanges(changes: SimpleChanges): void { const data = changes['data']?.currentValue; if (data) { this.updatePageSize(data); this.updatePager(data); } } onPage(event: MouseEvent, page: number): void { event.stopPropagation(); const current = this.data?.page?.page; const size = this.data?.page?.size; if (current === page) return; this.page.emit(new Page({ page: page, size: size })); } onPageSize(event: MouseEvent, size: number): void { event.stopPropagation(); const current = this.data?.page?.size; if (current === size) return; const page = this.data?.page ?? { page: 1, size: 100 }; const start = (page.page - 1) * page.size + 1; const newPage = Math.ceil(start / size); this.page.emit(new Page({ page: newPage, size: size })); } onSort(event: MouseEvent, header: Header): void { event.stopPropagation(); this.sort.emit(header); } private updatePageSize(data: Result): void { const size = data.page?.size ?? 20; const sizes = [10, 20, 50].map( (i) => new PageButton({ page: i, current: i === size }) ); this.pagesize = sizes; } private updatePager(data: Result): void { const page = data.page?.page ?? 1; const last = Math.ceil(data.total / (data.page?.size ?? data.total)); // get the list of pages const pages = [ 1, page + 1 > last ? page - 2 : 1, page - 1, page, page + 1, page < 3 ? 3 : last, last, ] // unique .filter((v, i, a) => a.indexOf(v) === i) // in range .filter((i) => 1 <= i && i <= last); const buttons = pages.map( (i) => new PageButton({ page: i, current: i === page, }) ); if (buttons.length > 2) { if (buttons[0].page !== buttons[1].page - 1) { buttons.splice(1, 0, new PageButton({ ellipsis: true })); } const length = buttons.length; if (buttons[length - 2].page !== buttons[length - 1].page - 1) { buttons.splice(length - 1, 0, new PageButton({ ellipsis: true })); } } this.pager = buttons; } } export class PageButton { page: number; current: boolean; ellipsis: boolean; constructor(data: Partial) { this.page = data?.page ?? -1; this.current = data?.current ?? false; this.ellipsis = data?.ellipsis ?? false; } }