Pagination divides a collection into manageable pages for presentation or retrieval. A product store can let users choose the page size and navigate numbered pages instead of viewing every product at once. section 5.5.3
A custom Angular implementation tracks and derives the page state:
- Store the products-per-page and selected-page values as signals. section 5.5.3
- Compute the available page numbers from the product count and page size. section 5.5.3
- Bind a page-size select and navigation buttons to component properties and methods. section 5.5.3
- Parse values received from HTML controls because statically defined options provide strings at runtime. section 5.5.3
For an administration table, Angular Material supplies a paginator. Add MatPaginatorModule, place the paginator alongside the table, and associate it with the MatTableDataSource after the view initializes. section 7.5.3
Product table pagination
A product table displays columns for identifiers, names, categories, prices, and actions. Connecting its data source to MatPaginator adds built-in pagination while preserving the table component’s existing structure. section 7.5.3
Listing 5.23. Adding pagination in the store.component.ts file in the src/app/store folder
import { Component, Signal, computed, signal } from "@angular/core";
import { Product } from "../model/product.model";
import { ProductRepository } from "../model/product.repository";
@Component({
selector: "store",
templateUrl: "store.component.html"
})
export class StoreComponent {
products: Signal<Product[]>;
categories: Signal<string[]>;
selectedCategory = signal<string | undefined>(undefined);
productsPerPage = signal(4);
selectedPage = signal(1);
pagedProducts: Signal<Product[]>;
pageNumbers: Signal<number[]>;
constructor(private repository: ProductRepository) {
this.products = computed(() => {
if (this.selectedCategory() == undefined) {
return this.repository.products();
} else {
return this.repository.products().filter(p =>
p.category === this.selectedCategory());
}
})
this.categories = repository.categories;
let pageIndex = computed(() => {
return (this.selectedPage() - 1) * this.productsPerPage()
});
this.pagedProducts = computed(() => {
return this.products().slice(pageIndex(),
pageIndex() + this.productsPerPage());
});
this.pageNumbers = computed(() => {
return Array(Math.ceil(this.products().length
/ this.productsPerPage()))
.fill(0).map((x, i) => i + 1);
});
}
changeCategory(newCategory?: string) {
this.selectedCategory.set(newCategory);
this.changePage(1);
}
changePage(newPage: number) {
this.selectedPage.set(newPage);
}
changePageSize(newSize: number) {
this.productsPerPage.set(Number(newSize));
this.changePage(1);
}
}
Inspect the custom StoreComponent implementation, including signal state and computed page-number generation. section 5.5.3
Listing 7.34. Connecting the paginator in the productTable.component.ts file in the src/app/admin folder
import { Component, IterableDiffer, IterableDiffers, ViewChild }
from "@angular/core";
import { MatTableDataSource } from "@angular/material/table";
import { Product } from "../model/product.model";
import { ProductRepository } from "../model/product.repository";
import { MatPaginator } from "@angular/material/paginator";
@Component({
templateUrl: "productTable.component.html"
})
export class ProductTableComponent {
colsAndRows: string[] = ['id', 'name', 'category', 'price', 'buttons'];
dataSource =
new MatTableDataSource<Product>(this.repository.products());
differ: IterableDiffer<Product>;
constructor(private repository: ProductRepository,
differs: IterableDiffers) {
this.differ = differs.find(this.repository.products()).create();
}
ngDoCheck() {
let changes = this.differ?.diff(this.repository.products());
if (changes != null) {
this.dataSource.data = this.repository.products();
}
}
deleteProduct(id: number) {
this.repository.deleteProduct(id);
}
@ViewChild(MatPaginator)
paginator? : MatPaginator
ngAfterViewInit() {
if (this.paginator) {
this.dataSource.paginator = this.paginator;
}
}
}
Inspect the Angular Material integration that queries MatPaginator and connects it to the table data source. section 7.5.3










