ngx-zen-table
v0.1.0
Published
Lightweight infinite-scroll Angular Material table with skeleton rows, selection, and auto-fill.
Maintainers
Readme
🧘♂️ ngx-zen-table
Lightweight infinite-scroll Angular Material table with skeleton loading, sticky headers, and row selection — built for Angular 20 and Signals.
✨ Features
- Infinite scrolling with automatic viewport fill
- Built-in skeleton rows during loading
- Sticky header (Material-compatible)
- Row selection (single / multiple / select-all visible)
- Works with Signals and OnPush / zoneless mode
- SSR-safe & debounce-optimized
- Minimal dependencies (only Angular + Material)
🚀 Installation
npm install ngx-zen-tablePeer dependencies required:
npm install @angular/core @angular/common @angular/material🧩 Usage example
import { Component, signal } from '@angular/core';
import { ZenTableComponent } from 'ngx-zen-table';
@Component({
selector: 'app-demo',
standalone: true,
imports: [ZenTableComponent],
template: `
<zen-table
[columns]="cols"
[fetchPage]="fetchPage"
[selectable]="true"
[stickyHeader]="true"
(selectionChange)="onSelect($event)">
</zen-table>
`,
})
export class DemoComponent {
cols = [
{ id: 'id', header: 'ID', width: 80, cell: (r: any) => r.id },
{ id: 'name', header: 'Name', cell: (r: any) => r.name },
];
fetchPage = async ({ page, pageSize }: any) => {
const total = 100;
const start = page * pageSize;
const items = Array.from({ length: Math.min(pageSize, total - start) }, (_, i) => ({
id: start + i + 1,
name: `Row ${start + i + 1}`,
}));
return { items, hasNext: start + pageSize < total };
};
onSelect(rows: any[]) {
console.log('Selected rows:', rows);
}
}⚙️ Inputs & Outputs
| Input | Type | Default | Description |
| ----------------- | --------------------------------- | ------------ | ---------------------------------- |
| columns | ZenColumn<T>[] | — | Column definitions |
| fetchPage | (params) => Promise<PageResult> | — | Async page loader |
| pageSizeHint | number | 25 | Initial page size |
| autoFill | boolean | true | Auto-compute rows to fill viewport |
| pageSizeCap | number | 200 | Max rows per auto-fill cycle |
| stickyHeader | boolean | false | Enables sticky header |
| selectable | boolean | false | Enables row selection |
| selectionMode | 'single' \| 'multiple' | 'multiple' | Selection mode |
| getRowKey | (row: T) => unknown | — | Unique key for selection |
| resetKey | number | 0 | Force internal reset |
| selectionChange | EventEmitter<T[]> | — | Emits current selection |
🧠 Notes
- Designed for Angular 20 / Signals.
- Fully compatible with Angular Material themes.
- Inline skeletons keep table height stable.
- No dependency on CDK virtual scroll — simpler & SSR-friendly.
🪄 Roadmap
- Sorting & filtering hooks
- Keyboard navigation
- cell templates
- Expandable rows
- Virtual scroll mode (optional CDK)
📝 License MIT © Cédric Sterkendries
