@firestitch/grid
A virtual-scrolling grid for Angular 18 that shows either a pivot (row levels, column levels and
values) or a source's own lines (details), with sorts and filters on every column header,
expandable groups, total rows and columns, and a layout panel docked beside it. The grid never
holds a dataset: it asks a GridSource for the rows on screen and reads more as the viewer
scrolls and opens groups.
Install
npm install @firestitch/grid
Like every Firestitch package, the grid declares no peer dependencies. The app installs the packages the grid imports itself:
| Package | Version | Used for |
|---|---|---|
@angular/core, common, forms, cdk, material | ^18.2.7 | |
rxjs | ^7.5.6 | |
@firestitch/chip | ^18.0.70 | the layout panel's field chips |
@firestitch/menu | ^18.0.5 | header and layout panel menus |
@firestitch/resize | ^18.0.3 | the layout panel's resize edge |
@firestitch/style | ^18.0.70 | the --fs-* colour tokens the grid paints with |
@firestitch/datepicker | ^18.0.29 | date column filters |
@firestitch/form | ^18.0.41 | filter panel validation |
@firestitch/popover | ^18.1.0 | the filter panel and truncated cells (panel mode, added in 18.1.0) |
An app must install every one of them, @firestitch/datepicker, @firestitch/form and
@firestitch/popover included: the app does not build without them, and @firestitch/popover
must be 18.1.0 or later. @firestitch/datepicker and @firestitch/form import
@firestitch/clear, common, date, dialog, drawer, message and scroll-picker, and
@firestitch/drawer needs @firestitch/core and @firestitch/store. An app that already uses
fs-datepicker has them.
Usage
fs-grid is a standalone component.
import { HttpClient } from '@angular/common/http';
import { Component, inject, signal } from '@angular/core';
import {
FsGridComponent,
GridAggregation,
GridGranularity,
GridLayout,
GridResult,
GridSource,
} from '@firestitch/grid';
@Component({
selector: 'app-sales-grid',
standalone: true,
imports: [FsGridComponent],
template: '<fs-grid [source]="source" [(layout)]="layout"></fs-grid>',
})
export class SalesGridComponent {
public layout = signal<GridLayout>({
rows: [{ field: 'region' }],
columns: [{ field: 'orderedOn', granularity: GridGranularity.Month }],
values: [{ field: 'revenue', aggregation: GridAggregation.Sum }],
totalRow: true,
});
public source: GridSource = {
read: (request, params) => this._http.post<GridResult>('/sales/grid', { request, params }),
};
private _http = inject(HttpClient);
}
Inputs
| Input | Type | |
|---|---|---|
source | GridSource | Required. The only way the grid reaches its data. |
[(layout)] | GridLayout | Required. Sorts, filters, header drags and the layout panel write it back, canonical. |
controls | GridControls | What the viewer may change (sort, expand, layout, filter): enabled, disabled or hidden. A control left out is enabled. |
params | GridParams | The host's own values, carried on every read. The grid never looks inside. |
[(expansion)] | GridExpansion | Which groups are open: every group down to depth, then the viewer's own opens and closes. |
[(panel)] | GridPanel | null | The panel docked beside the grid; null when none is open. |
formatter | GridFormatter | Writes every value the grid shows, so the screen and the host's own files read the same. The grid's en-US formatter is used when absent. |
clearedFilter | { field, granularity } | null | A date filter the host took out when the grain its params drive changed; the status line names it. |
The source
export interface GridSource {
read(request: GridRequest, params: GridParams): Observable<GridResult>;
}
- Each emit is a part of the answer, and complete means done.
- The read is cold, and unsubscribing aborts it. The grid cancels reads it no longer needs.
request.rowsnames the row ranges wanted,request.columnsthe column range, andrequest.fieldsasks for the source's fields and limits too.- An error arrives as an
Errorwith a readable message; the grid shows it with a Retry.
Layout helpers
canonicalGridLayout(layout)gives the layout as a host stores and compares it: defaults are left out and keys come in one order, so two layouts that mean the same have the same JSON.normalizeGridLayout(layout)is the forgiving read: unknown keys and entries without a field are dropped, and every list and flag comes back present.
Styles
The grid paints from its own component styles, the --fs-* tokens of @firestitch/style and the
Angular Material theme. There is nothing to include: the package's styles.scss is empty and
ships only so the build lays out like the other Firestitch packages.
Development
npm run serve # the playground, with every example
npm run check # the engine, contract and client checks
npm run package # the checks, then package/ with this README and the LICENSE
License
MIT. See LICENSE.