Skip to content
AdaptTable

Angular realtime table updates

Keep live rows in an Angular signal and update that signal when a feed delivers patches. injectRowPatchStream() under @adapttable/angular/stream connects a WebSocket or server-sent-events endpoint to the host-owned array. It does not make the table a database or a write transport.

import { Component, signal } from "@angular/core";
import type { ColumnDef } from "@adapttable/angular";
import { injectRowPatchStream } from "@adapttable/angular/stream";
import { AdaptDataTable } from "@adapttable/angular-unstyled";
interface Stock {
id: string;
product: string;
available: number;
}
@Component({
selector: "app-live-stock",
imports: [AdaptDataTable],
template: `
<button type="button" (click)="enabled.set(!enabled())">
{{ enabled() ? "Pause live updates" : "Resume live updates" }}
</button>
<p role="status">Feed: {{ stream.status() }}</p>
@if (stream.error(); as error) {
<p role="alert">{{ error.message }}</p>
}
<adapt-data-table
tableLabel="Live stock"
[data]="rows()"
[columns]="columns"
[rowKey]="rowKey"
/>
`,
})
export class LiveStock {
readonly rows = signal<readonly Stock[]>([
{ id: "s1", product: "Notebook", available: 10 },
]);
readonly enabled = signal(true);
readonly rowKey = (row: Stock) => row.id;
readonly columns: readonly ColumnDef<Stock>[] = [
{ key: "product", header: "Product" },
{ key: "available", header: "Available" },
];
readonly stream = injectRowPatchStream<Stock>({
eventSource: "/api/stock/events",
enabled: this.enabled,
getRowId: this.rowKey,
onPatch: (update) => this.rows.update(update),
});
}

Use a real application endpoint in place of /api/stock/events. The default frame format is a JSON patch array, for example [{"type":"update","id":"s1","changes":{"available":9}}]. A custom parse function can adapt another protocol. Use the NG-ZORRO root table if that is your kit; the stream entry remains on the binding. See getting started for installation and first-release status.

Choose websocket or eventSource; SSE also accepts an event name and WebSockets can supply subprotocols. URLs and enabled may be signals. Changing the URL or disabling the feed closes the prior connection; destroying the injection context closes it too. The returned status and error are signals. close() closes the current connection; a later URL/enabled change can open it again. Use enabled: false as the maintained paused state.

reconnect configures reconnection. Reopening a transport is not proof that missed data was replayed: the host protocol must decide how to resume, refetch or reconcile after a gap. Invalid default-format frames with no valid patches leave the row array unchanged. Validate incoming business values and permissions at your service boundary; do not let a feed grant new editing rights.

The injector opens the feed as part of its reactive lifecycle. On an SSR route, enable a browser-only feed after client render when it should not connect on the server, while keeping the initial rows identical for hydration.

applyRowPatches, updateRow, insertRow, upsertRow and removeRow are neutral helpers from @adapttable/core. Apply them inside rows.update(...) for a save response, timer or an existing host socket. Updates preserve untouched row objects and no-op patches preserve the array reference. Stable keys retain selection and expansion identity; an update to a missing ID is a no-op, while an upsert can append a missing record.

For changed-cell feedback, use applyRowPatchesWithLog to obtain { rows, events }, call injectChangedCellFlash({ enabled: true }).mark(events), and pass the flash reader through [isCellFlashing]. The shell stamps data-flash on matching desktop cells and mobile values. The unstyled kit needs your CSS for a visible tint. Reduced-motion preferences suppress the flash, and the injector clears timers when destroyed.

Keep connection status and failures available as text, not only animation. Pause/Resume should be reachable by touch and keyboard. For live updates that arrive under an active edit, configure the editing conflict policy and row version rather than silently overwriting a draft.

See Data tiers, SSR and the stream implementation.

Third-party notices