Skip to content

Custom rendering ​

Use class hooks when markup does not need to change. Use render callbacks when a header or cell needs framework-native content such as a badge, link, icon, or product component. The grid keeps sorting, editing, selection, focus, and ARIA structure around the rendered content.

Choose the smallest override ​

  1. Use getHeaderClassName and getCellClassName for CSS-only changes.
  2. Use columnDef.header or columnDef.cell when one column owns the rendering.
  3. Use renderHeader or renderCell for a product-wide rendering policy.

The global render callback runs first. Returning null or undefined falls back to the column callback and then to Open Grid's default text rendering.

React ​

tsx
<DataGrid
  data={invoices}
  columns={columns}
  getRowId={(invoice) => invoice.id}
  renderHeader={({ column }) => <strong>{column.id}</strong>}
  renderCell={({ column, row, value }) =>
    column.id === "status"
      ? <StatusBadge status={String(value)} />
      : <a href={`/invoices/${row.id}`}>{String(value ?? "")}</a>
  }
/>

Callbacks receive typed core HeaderContext<TData, TValue> and CellContext<TData, TValue> values. A column-level callback uses the same context.

Vue ​

ts
h(InvoiceGrid, {
  options,
  renderHeader: ({ column }) => h("strong", column.id),
  renderCell: ({ column, row, value }) =>
    column.id === "status"
      ? h(StatusBadge, { status: String(value) })
      : h("a", { href: `/invoices/${row.id}` }, String(value ?? "")),
});

createDataGrid<Invoice>() preserves row typing for these callbacks.

Svelte ​

Svelte callbacks return a typed renderer descriptor. This keeps component creation inside Svelte instead of attempting to render framework objects as strings.

svelte
<script lang="ts">
  import DataGrid from "@open-grid/svelte-ui/DataGrid.svelte";
  import { createSvelteDataGridRenderer } from "@open-grid/svelte-ui";
  import InvoiceCell from "./InvoiceCell.svelte";

  const renderCell = createSvelteDataGridRenderer(InvoiceCell);
</script>

<DataGrid {options} {renderCell} />

The component receives the typed context as a context prop:

svelte
<script lang="ts">
  import type { CellContext } from "@open-grid/core";
  export let context: CellContext<Invoice, unknown>;
</script>

<a href={`/invoices/${context.row.id}`}>{String(context.value ?? "")}</a>

Pass a second object to createSvelteDataGridRenderer(Component, props) for stable component props shared by every invocation. The helper supports Svelte 4.2.20 and Svelte 5.

Performance boundary ​

Render callbacks run for mounted cells, not every row in a virtualized dataset. Keep callback and component identities stable, and avoid product-side scans of the full dataset during each render. Use getCellClassName instead of a custom component when a semantic class is sufficient.

Released under the MIT License.