src/app/core/common-components/entities-table/list-paginator/list-paginator.component.ts

Metadata

Relationships

Depends on

  • MatPaginatorModule
  • )

Index

Properties
Methods
Inputs
Accessors

Constructor

constructor()

Inputs

dataSource
Type : MatTableDataSource<E>
idForSavingPagination
Type : string

Methods

onPaginateChange
onPaginateChange(event: PageEvent)
Parameters :
Name Type Optional
event PageEvent No
Returns : void

Properties

Readonly LOCAL_STORAGE_KEY
Type : string
Default value : "PAGINATION-"
Readonly pageSize
Type : unknown
Default value : signal(10)
Readonly pageSizeOptions
Type : []
Default value : [10, 20, 50, 100]
paginator
Type : MatPaginator
showFirstLast
Type : unknown
Default value : computed( () => !(this.dataSource() instanceof PaginatedDataSource), )

Accessors

paginatorRef
setpaginatorRef(paginator: MatPaginator)
Parameters :
Name Type Optional
paginator MatPaginator No
Returns : void
import {
  ChangeDetectionStrategy,
  Component,
  computed,
  effect,
  inject,
  input,
  signal,
  SkipSelf,
  ViewChild,
} from "@angular/core";
import {
  MatPaginator,
  MatPaginatorIntl,
  MatPaginatorModule,
  PageEvent,
} from "@angular/material/paginator";
import { MatTableDataSource } from "@angular/material/table";
import { PaginatedDataSource } from "#src/app/core/common-components/entities-table/data-source/paginated-data-source";
import { UnknownTotalPaginatorIntl } from "./unknown-total-paginator-intl";
import { LOCAL_STORAGE_TOKEN } from "#src/app/utils/di-tokens";

@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: "app-list-paginator",
  templateUrl: "./list-paginator.component.html",
  styleUrls: ["./list-paginator.component.scss"],
  imports: [MatPaginatorModule],
  providers: [
    {
      // component-scoped intl so the "10+" range label only affects this paginator;
      // delegates to the app-wide (translated) intl for everything else
      provide: MatPaginatorIntl,
      useFactory: (parent: MatPaginatorIntl) =>
        new UnknownTotalPaginatorIntl(parent),
      deps: [[new SkipSelf(), MatPaginatorIntl]],
    },
  ],
})
export class ListPaginatorComponent<E> {
  private readonly localStorage = inject(LOCAL_STORAGE_TOKEN);
  private readonly paginatorIntl = inject(
    MatPaginatorIntl,
  ) as UnknownTotalPaginatorIntl;
  readonly LOCAL_STORAGE_KEY = "PAGINATION-";
  readonly pageSizeOptions = [10, 20, 50, 100];

  dataSource = input<MatTableDataSource<E>>();
  idForSavingPagination = input<string>();
  showFirstLast = computed(
    () => !(this.dataSource() instanceof PaginatedDataSource),
  );

  private readonly paginatorReady = signal(false);
  @ViewChild(MatPaginator, { static: true })
  set paginatorRef(paginator: MatPaginator) {
    this.paginator = paginator;
    this.paginatorReady.set(!!paginator);
  }
  paginator: MatPaginator;

  readonly pageSize = signal(10);

  constructor() {
    effect(() => {
      if (this.idForSavingPagination() !== undefined) {
        this.applyUserPaginationSettings();
      }
    });

    effect(() => {
      this.paginatorReady();
      this.bindPaginator(this.dataSource());
    });

    effect(() => {
      const dataSource = this.dataSource();
      // only server-side paginated data sources have an unknown total
      const hasUnknownTotalCount =
        dataSource instanceof PaginatedDataSource &&
        dataSource.hasUnknownTotalCount();

      if (this.paginatorIntl.hasUnknownTotalCount !== hasUnknownTotalCount) {
        this.paginatorIntl.hasUnknownTotalCount = hasUnknownTotalCount;
        // notify the MatPaginator to re-render its range label
        this.paginatorIntl.changes.next();
      }
    });
  }

  onPaginateChange(event: PageEvent) {
    this.pageSize.set(event.pageSize);
    this.savePageSize(this.pageSize());
  }

  private applyUserPaginationSettings() {
    const savedSize = this.getSavedPageSize();
    this.pageSize.set(
      savedSize && savedSize !== -1 ? savedSize : this.pageSize(),
    );
  }

  private getSavedPageSize(): number {
    return Number.parseInt(
      this.localStorage.getItem(
        this.LOCAL_STORAGE_KEY + this.idForSavingPagination(),
      ),
    );
  }

  private savePageSize(size: number) {
    this.localStorage.setItem(
      this.LOCAL_STORAGE_KEY + this.idForSavingPagination(),
      size?.toString(),
    );
  }

  private bindPaginator(dataSource: MatTableDataSource<E> | undefined) {
    if (!dataSource || !this.paginator) return;
    dataSource.paginator = this.paginator;
  }
}
<mat-paginator
  (page)="onPaginateChange($event)"
  [pageSize]="pageSize()"
  [pageSizeOptions]="pageSizeOptions"
  [showFirstLastButtons]="showFirstLast()"
></mat-paginator>

./list-paginator.component.scss

@use "variables/sizes";

/* The paginator is usually a little smaller than this */
$approx-width-paginator: 450px;
$slider-padding-all: 16px;

:host {
  display: flex;
  flex-direction: row;
  align-items: center;

  justify-content: flex-start;
  background-color: white;

  @media all and (max-width: $approx-width-paginator) {
    flex-direction: column-reverse;
    align-items: flex-start;
  }
}

.slider {
  padding-left: sizes.$regular;
  font-size: small;

  @media all and (max-width: $approx-width-paginator) {
    padding-bottom: sizes.$regular;
  }
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""