Rendering
Rows are virtualized automatically; on top of that, cells accept custom renderers — plain functions, classes, or framework components — and rows accept semantic presentation, conditional classes, and full-width takeovers.
- React
- Angular
- Core TypeScript
function StatusBadge({ value }: CellRendererParams) {
return <span className={"status status-" + String(value).toLowerCase()}>{String(value)}</span>;
}
const columns: ReactColDef[] = [
{ key: "status", label: "Status", cellRenderer: StatusBadge },
{
colId: "trend",
label: "Trend",
valueGetter: (row) => row.monthlyRevenue,
cellRenderer: SparklineRenderer,
cellRendererParams: { type: "area", showPoints: true },
},
];
<Grid rowData={rows} columnDefs={columns} zebraRows columnHover />
// Any Angular component works in a cell slot; params arrive as an input.
columns: NgColDef[] = [
{ key: "status", label: "Status", cellRenderer: StatusBadgeComponent },
{
colId: "trend",
label: "Trend",
valueGetter: (row: Order) => row.monthlyRevenue,
cellRenderer: SparklineRenderer,
cellRendererParams: { type: "area", showPoints: true },
},
];
<awb-grid [rowData]="rows" [columnDefs]="columns" [zebraRows]="true" />
const core = new GridCore(measurer, {
columnDefs: [
{
key: "status",
label: "Status",
cellRenderer: ({ value }) => {
const badge = document.createElement("span");
badge.className = "status status-" + String(value).toLowerCase();
badge.textContent = String(value);
return badge;
},
},
{
colId: "trend",
label: "Trend",
valueGetter: (row) => row.monthlyRevenue,
cellRenderer: SparklineRenderer,
cellRendererParams: { type: "area", showPoints: true },
},
],
zebraRows: true,
});
Virtual scrolling and overscan
const options = {
rowHeight: 40,
overscanRowCount: 8,
} satisfies GridOptions;
Virtualization is automatic: the renderer maintains a small reusable row pool and slides it over the current viewport. Left, center, and right column sections stay synchronized without additional configuration.
Function cell renderer
const column = {
key: "status",
label: "Status",
cellRenderer: ({ value }) => {
const badge = document.createElement("span");
badge.className = `status status-${String(value).toLowerCase()}`;
badge.textContent = String(value);
return badge;
},
} satisfies ColDef;
Class renderers implement init, getGui, and optional refresh/destroy.
The React and Angular bindings additionally accept framework components in the
same cellRenderer slot, as the tabs above show.
Built-in renderers: change flash and Sparkline
const priceColumn = {
key: "price",
label: "Price",
type: ColumnType.CURRENCY,
cellRenderer: ChangeFlashCellRenderer,
cellRendererParams: { cellFlashDuration: 400, cellFadeDuration: 900 },
} satisfies ColDef;
const trendColumn = {
colId: "trend",
label: "Trend",
valueGetter: (row) => row.monthlyRevenue,
cellRenderer: SparklineRenderer,
cellRendererParams: {
type: "area",
showPoints: true,
tooltipValueFormatter: ({ xValue, yValue }) => `${xValue}: $${yValue}`,
},
} satisfies ColDef;
Grid-wide flash defaults are available as cellFlashDuration and
cellFadeDuration. Sparkline data may be number[] or [xValue, number][];
supported visuals are line, area, and bar.
Row presentation
For a semantic state shared by every cell in a row, supply one row presentation instead of repeating cell callbacks across columns:
const pendingIds = new Set(["order-42"]);
const options = {
getRowPresentation: ({ rowId }) => pendingIds.has(rowId) ? {
rowClass: "row-pending",
cellClass: "cell-pending",
cellStyle: { opacity: "0.7" },
editable: false,
tooltip: {
content: "Saving changes",
options: { mode: "follow" },
},
accessibility: {
description: "Changes to this row are being saved",
busy: true,
},
metadata: { status: "pending" },
} : undefined,
} satisfies GridOptions;
// Required only when the captured Set changes without a row transaction.
api.refreshRowPresentation();
Explicit column tooltip content/options override the row defaults. Cell classes
compose; cell inline styles merge with the column winning conflicting fields.
editable: false prevents user editing in columns that inherit the row gate; it
does not enable columns when true. A deliberate exception can set
inheritRowPresentation: { editable: false }.
Full-width rows
const options = {
isFullWidthRow: (node) => node.data?.kind === "notice",
fullWidthCellRenderer: ({ data }) => {
const element = document.createElement("strong");
element.textContent = data.message;
return element;
},
} satisfies GridOptions;
Full-width rows are client-side and retain the standard row height.
Conditional rows and visual states
const options = {
rowHover: true,
columnHover: true,
zebraRows: true,
getRowClass: ({ data }) => data.overdue ? "row-overdue" : undefined,
getRowStyle: ({ data }) => ({ opacity: data.archived ? "0.6" : "1" }),
} satisfies GridOptions;
Loading and empty overlays
<Grid
loading={isLoading}
loadingMessage="Loading orders…"
noRowsMessage="No orders match this view"
/>
For the framework-neutral API:
api.dispatch({ type: "overlayShow", overlayType: "loading" });
api.dispatch({ type: "overlayShow", overlayType: "none" });
The no-rows overlay appears automatically for an empty model and distinguishes an empty data set from a filtered-out result.