@lightfastgrid/angular
v0.2.0
Published
Angular package for LightFastGrid, a JavaScript data grid for large client-side datasets.
Maintainers
Readme
LightFastGrid for Angular
@lightfastgrid/angular integrates LightFastGrid with standalone Angular
components. It is MIT licensed. The declared @angular/core and
@angular/common peer range is exactly
^20.3.0 || ^21.0.0 || ^22.0.0.
Install
Install from npm when the package release is available:
npm install @lightfastgrid/angular @lightfastgrid/corepnpm add @lightfastgrid/angular @lightfastgrid/coreyarn add @lightfastgrid/angular @lightfastgrid/coreCore is also a runtime dependency of the Angular package. Declare it directly because the example imports its CSS and types; pnpm's strict resolution does not expose nested dependencies to application imports.
Quick start
import { Component } from '@angular/core';
import { LightFastGridComponent } from '@lightfastgrid/angular';
import type { ColumnDef, RowData } from '@lightfastgrid/core';
type Order = { id: string; customer: string; total: number };
@Component({
selector: 'orders-page',
standalone: true,
imports: [LightFastGridComponent],
template: `
<light-fast-grid
[rows]="rows"
[columns]="columns"
[getRowId]="getRowId"
[height]="420"
[accessibility]="{ ariaLabel: 'Orders' }"
/>
`,
})
export class OrdersPage {
readonly rows: Order[] = [
{ id: 'order-1001', customer: 'Acme', total: 1200 },
{ id: 'order-1002', customer: 'Globex', total: 850 },
];
readonly columns: ColumnDef[] = [
{ field: 'customer', headerName: 'Customer' },
{ field: 'total', headerName: 'Total' },
];
readonly getRowId = (row: RowData): string => String(row.id);
}Use OrdersPage in an existing Angular application's route or in another
standalone component's imports. Declaring this class does not bootstrap an
application; keep the application's own bootstrap and provider setup.
Sizing and theme CSS
light-fast-grid is a block host with default height 100%. A numeric
height is CSS pixels. Class, style, id, and data attributes stay on this
element. The host is a static ngSkipHydration boundary. Height and host
attributes do not perform Core data work.
Import the default theme once in global application styles (for example,
src/styles.css), not in component-scoped styles:
@import '@lightfastgrid/core/themes/default.css';The Angular JavaScript entry does not import this CSS (it is not JS-imported). A blank or clipped Grid usually means the host or its parent has no real height.
Data updates and API readiness
Bindings are shallow. Replace the top-level rows array, columns array, or
configuration object when changing declarative data; nested mutation is not
watched. Core owns row identity, immutable diffing, transactions, and ordinary
cell rendering. getRowId must return a unique stable value for each row.
Use #grid="lightFastGrid" or a typed view query to access grid.api. The
stable handle becomes usable inside (gridReady). Before readiness and after
disposal its methods throw LFG_ANGULAR_GRID_NOT_READY; there is no
getInstance() or unsupported adaptor setter. Construction begins after
afterNextRender in the browser. Initial-only options require component
recreation to change.
The application chooses zone-based provideZoneChangeDetection() or
provideZonelessChangeDetection() in its own bootstrap configuration. The
package has no zone.js peer and does not choose change-detection mode.
Acceptance covered Angular 20.3.0/20.3.31, 21.0.0/21.2.23, and 22.0.0/22.1.6 with compatible isolated TypeScript tooling.
Optional Core booleans such as loading stay undefined when omitted. Bind
[loading]="true"; do not rely on a bare boolean attribute.
There is no Grid during component construction or SSR.
Capabilities and limits
Core provides virtualized rows and columns, sorting, filtering, selection, editing, pagination, CSV export, keyboard navigation, and eligible Worker work. Angular templates are supported only for row actions, header actions, grid overlays, and cell-shell overlays; ordinary cells remain Core-rendered.
Server rendering produces the surrounding Angular parent and an empty Grid
host. Client hydration preserves that parent and creates one client Grid; this
is not server-rendered cells or incremental hydration. A later nested user
component constructor that throws can abort Angular view creation before an
already-created sibling's DestroyRef or takeUntilDestroyed cleanup runs.
Adaptor-owned resources are still released. A shared Core queued-scroll popup
issue can immediately close a row-action menu when clicking a previously
offscreen trigger during horizontal auto-scroll; it is not an Angular-only fix.
Inputs and update ownership
Bindings are shallow. Replace rows, columns, registries, and configuration objects to request an update; in-place mutation is not watched. One microtask coalesces a fixed inventory of changed inputs. The wrapper does not traverse or copy rows. Core owns row identity, immutable diffing, transactions, selection, sorting, filtering, workers, and ordinary cell rendering.
Live inputs are:
rows, immutableRows, columns, defaultColDef, rowSelection,
columnSelection, columnOrder, rowDrag, rowClass, getRowClass,
rowClassRules, pagination, paginationPageSize,
paginationPageSizeOptions, theme, floatingFilters, columnGroupHeaders,
quickFilter, quickFilterText, columnMenu, cellMenu, cellRenderers,
headerRenderers, cellShellOverlays, csvExport,
asyncTransactionWaitMillis, execution, loading, overlays,
accessibility, and onBeforeCellEditCommit.
getRowId, rowPinning, initialSortModel, suppressRowVirtualization, and
suppressColumnVirtualization are initial-only. Changing one after mount emits
one development warning per key and requires component recreation. getParentId,
mode, and rowModelType are reserved Core construction options; V1 does not
invent tree or server-row behavior. height changes only the Angular host.
Undefined clears a changed live input according to Core semantics, except
quickFilterText: undefined relinquishes declarative control and '' clears
the current query. rows and columns clear to empty arrays. Equivalent
pagination and quick-filter objects preserve imperative state. Optional Core
booleans stay undefined when omitted.
onBeforeCellEditCommit is a synchronous input hook, not an output. Its latest
function runs inside Angular while Core retains its existing exception policy.
API readiness and commands
Reference the exported component with #grid="lightFastGrid" or a typed view
query. grid.api is stable for the Angular component lifetime and resolves the
current client Grid at each call. It is ready inside (gridReady). Before that
event and after disposal, every method throws an Error whose code is exactly
LFG_ANGULAR_GRID_NOT_READY.
The handle exposes Core GridApi commands, including selection, sorting,
filtering, transactions, pagination, CSV export, sizing, focus, and
setOverlays. It intentionally exposes no mount, destroy, getInstance,
raw Core Grid, or adaptor setters. Async transaction/search/export results,
task identity, progress, cancellation, and errors remain Core-owned. Destroying
the component invalidates wrapper delivery before Core and custom views are
released, so late work cannot emit stale outputs into the removed parent.
Outputs
gridReady has no payload. Use (gridReady)="onReady()", not a required
$event handler. The 23 output names are:
gridReady, columnResized, sortChanged, filterChanged,
selectionChanged, columnSelectionChanged, columnOrderChanged,
columnPinChanged, rowPinChanged, columnVisibilityChanged,
rowOrderChanged, cellValueChanged, paginationChanged,
focusedCellChanged, cellShellAction, rowDataUpdated,
quickFilterChanged, quickSearchPendingChanged, asyncTransactionsFlushed,
csvExportProgress, csvExportCompleted, csvExportCancelled,
csvExportError.
Template markers
Row actions, header actions, grid overlays, and cell-shell overlays use typed
ng-template markers (lfgRowAction, lfgHeaderAction, lfgOverlay,
lfgCellShellOverlay). Registry factories receive the Core context with
host stripped and must return { template } or null. Overlay visibility,
precedence, host reuse, and cell-shell close/replacement scheduling stay in
Core. Unchanged overlay inputs do not undo a live api.setOverlays call.
This standalone example adds a custom row-action template and a loading overlay to the same small Orders dataset. It includes its imports and sizing; use it in an existing Angular application as described above.
import { Component, ViewChild } from '@angular/core';
import {
type AngularCellRendererRegistry,
type AngularGridOverlaysOptions,
LightFastGridComponent,
LightFastGridOverlayDirective,
LightFastGridRowActionDirective,
} from '@lightfastgrid/angular';
import type { ColumnDef, RowData } from '@lightfastgrid/core';
type Order = { id: string; customer: string };
@Component({
selector: 'orders-with-templates',
standalone: true,
imports: [
LightFastGridComponent,
LightFastGridRowActionDirective,
LightFastGridOverlayDirective,
],
template: `
<ng-template lfgRowAction #rowAction="lfgRowAction" let-ctx>
<button type="button" (click)="ctx.close()">{{ ctx.rowId }}</button>
</ng-template>
<ng-template lfgOverlay #overlay="lfgOverlay" let-ctx>
<div>{{ ctx.kind }}</div>
</ng-template>
<light-fast-grid
[rows]="rows"
[columns]="columns"
[getRowId]="getRowId"
[cellRenderers]="cellRenderers"
[overlays]="overlays"
[height]="420"
[accessibility]="{ ariaLabel: 'Orders' }"
/>
`,
})
export class OrdersWithTemplates {
@ViewChild('rowAction', { static: true })
rowAction!: LightFastGridRowActionDirective;
@ViewChild('overlay', { static: true })
overlay!: LightFastGridOverlayDirective;
readonly rows: Order[] = [{ id: 'order-1001', customer: 'Acme' }];
readonly columns: ColumnDef[] = [
{ field: 'customer', headerName: 'Customer' },
{ field: 'actions', headerName: 'Actions', cellKind: 'actions', actionsKey: 'row' },
];
readonly getRowId = (row: RowData): string => String(row.id);
readonly cellRenderers: AngularCellRendererRegistry = {
row: {
kind: 'actions',
mode: 'custom',
render: () => ({ template: this.rowAction.template }),
},
};
readonly overlays: AngularGridOverlaysOptions = {
loading: {
render: () => ({ template: this.overlay.template }),
},
};
}The exact $implicit contexts are AngularRowActionRenderContext,
AngularHeaderActionRenderContext, AngularOverlayRenderContext, and
AngularCellShellOverlayRenderContext. They retain the documented Core grid
API but never expose the Core DOM host. Templates retain their declaration
injection context and support bindings, pipes, nested components, signals, and
AsyncPipe. Initial content is mounted synchronously because row-action focus
depends on DOM existing before the trigger click returns.
Each successful factory result may include cleanup. It runs exactly once when
that Core host releases the Angular tree, including partial mount failure. The
wrapper destroys embedded views, effects, subscriptions, and its private child
root while preserving the reusable Core host. Open leases retain only active
custom content; there is no historical lease list or view reuse.
User code that throws from a template, ngOnInit, or an initial effect is
cleaned up while preserving the original thrown value. One Angular limitation
is explicit: if a later nested component constructor throws, Angular can abort
creation before DestroyRef callbacks or takeUntilDestroyed resources of an
already-created sibling run. Ordinary Angular view creation behaves the same,
and this package does not use private Angular view fields to work around it. The
adaptor still releases everything it owns.
SSR and hydration
Server rendering produces the surrounding Angular parent and an empty
light-fast-grid host. It does not construct Core Grid, render rows, or require
browser globals. The host is a static ngSkipHydration boundary. During client
hydration Angular preserves the surrounding parent DOM and initializes exactly
one client Grid inside that boundary after render. Parent event handlers remain
hydrated normally. Destroying the Angular application tears down the client Grid.
This is host-only SSR with a client-owned grid boundary. It is not server-rendered cells, incremental hydration, or deferred hydration.
Module format
Angular Package Format ESM/FESM plus index.d.ts. CommonJS is not supported.
Consumers must compile with the Angular compiler / linker.
Links
- LightFastGrid website
- Core quick start (framework-neutral behavior)
- Core runtime API reference
- Repository
- Issues
- MIT license
License
MIT. See LICENSE.
