Skip to content

Custom Cell Components

Community

A column’s renderer controls how each cell draws its content. It can be the name of a registered renderer (like 'text' or 'checkbox') or a CellRenderer instance you write yourself. Renderers are DOM-based and pooled, so they stay fast during virtualized scrolling.

interface CellRenderer {
/** First render into a pooled element. */
render(element: HTMLElement, params: RenderParams): void;
/** Update an existing element when the value changes (hot path — keep it cheap). */
update(element: HTMLElement, params: RenderParams): void;
/** Cleanup before the element returns to the pool. */
destroy?(element: HTMLElement): void;
}

Pass a renderer directly on the column definition:

const statusPill: CellRenderer = {
render(el, params) {
el.className = 'pill';
this.update(el, params);
},
update(el, params) {
el.textContent = String(params.value);
el.dataset.tone = params.value === 'Active' ? 'ok' : 'muted';
},
};
columns: [
{ field: 'status', header: 'Status', width: 140, renderer: statusPill },
]

Register once, then reference it by name from any column. This is handy when the same renderer is reused across columns or configured from data.

grid.registerRenderer('statusPill', statusPill);
grid.updateOptions({
columns: [
{ field: 'status', header: 'Status', width: 140, renderer: 'statusPill' },
],
});

For custom header rendering, register with grid.registerHeaderRenderer(name, renderer) and set the column’s header.type to 'custom' — see Headers.

Custom cell components