Custom Renderers

Register custom cell and header renderers.

Custom renderers let you control DOM output while keeping ZenGrid’s virtualization model.

Cell Renderer

progress-renderer.ts
import type { CellRenderer } from '@zengrid/core';
export const progressRenderer: CellRenderer = {
render(element, { value }) {
const percent = Number(value);
element.innerHTML = `<div class="bar"><span style="width: ${percent}%"></span></div>`;
},
update(element, params) {
this.render(element, params);
},
destroy(element) {
element.textContent = '';
},
};
register-renderer.ts
grid.registerRenderer('progress', progressRenderer);
const columns: ColumnDef[] = [
{ field: 'progress', header: 'Progress', width: 180, renderer: 'progress' },
];

Header Renderer

header-renderer.ts
import type { HeaderRenderer } from '@zengrid/core';
export const compactHeaderRenderer: HeaderRenderer = {
render(element, { column }) {
element.textContent = String(column?.header ?? '');
element.className = 'compact-header';
},
update(element, params) {
this.render(element, params);
},
destroy(element) {
element.textContent = '';
element.className = '';
},
};
register-header-renderer.ts
grid.registerHeaderRenderer('compact', compactHeaderRenderer);
const columns: ColumnDef[] = [
{
field: 'name',
header: { text: 'Name', type: 'custom', renderer: 'compact' },
width: 220,
},
];

Performance Rules

  • Keep generated DOM stable and small.
  • Avoid synchronous layout measurement in render() and update().
  • Clean up event listeners and element state in destroy().
  • Prefer CSS classes over inline style churn for repeated updates.
Warning

A slow renderer can make a virtualized grid feel slow. Test custom renderers with realistic row counts and scroll speed.