Skip to content

DataGridElement

High-performance data grid web component (<tbw-grid>).

Do not call the constructor directly. Use one of these approaches:

// Recommended: Use createGrid() for TypeScript type safety
import { createGrid, SelectionPlugin } from '@toolbox-web/grid/all';
const grid = createGrid<Employee>({
columns: [
{ field: 'name', header: 'Name' },
{ field: 'email', header: 'Email' }
],
plugins: [new SelectionPlugin()]
});
grid.rows = employees;
document.body.appendChild(grid);
// Alternative: Query existing element from DOM
import { queryGrid } from '@toolbox-web/grid';
const grid = queryGrid<Employee>('#my-grid');
// Alternative: Use document.createElement (loses type inference)
const grid = document.createElement('tbw-grid');
EventDescriptionTriggered By
sort-changeColumn header clicked to change sort order(internal)
column-resizeColumn resized by dragging(internal)
activate-cellCell activated (Enter key pressed)(internal)
mount-external-viewExternal view renderer needed (framework adapters)(internal)
mount-external-editorExternal editor renderer needed (framework adapters)(internal)
cell-changeFor each field that changed on each rowupdateRow(), updateRows()
column-state-changeEmitted when column visibility changessetColumnVisible(), toggleColumnVisibility(), showAllColumns(), setColumnOrder(), resetColumnState()
PropertyTypeDescription
tagNametbw-grid
versionstringVersion of the grid component, injected at build time from package.json

Get or set the row data displayed in the grid.

The getter returns processed rows (after filtering, sorting, grouping by plugins). The setter accepts new source data and triggers a re-render.

rows: T[]
// Set initial data
grid.rows = employees;
// Update with new data (triggers re-render)
grid.rows = [...employees, newEmployee];
// Read current (processed) rows
console.log(`Displaying ${grid.rows.length} rows`);

Get the original unfiltered/unprocessed source rows.

Use this when you need access to all source data regardless of active filters, sorting, or grouping applied by plugins. The rows property returns processed data, while sourceRows returns the original input.

sourceRows: T[]
// Get total count including filtered-out rows
console.log(`${grid.rows.length} of ${grid.sourceRows.length} rows visible`);
// Export all data, not just visible
exportToCSV(grid.sourceRows);

Get or set the column configurations.

The getter returns processed columns (after plugin transformations). The setter accepts an array of column configs or a column config map.

columns: ColumnConfig<T>[]
// Set columns as array
grid.columns = [
{ field: 'name', header: 'Name', width: 200 },
{ field: 'email', header: 'Email' },
{ field: 'role', header: 'Role', width: 120 }
];
// Set columns as map (keyed by field)
grid.columns = {
name: { header: 'Name', width: 200 },
email: { header: 'Email' },
role: { header: 'Role', width: 120 }
};
// Read current columns
grid.columns.forEach(col => {
console.log(`${col.field}: ${col.width ?? 'auto'}`);
});

Get or set the full grid configuration object.

The getter returns the effective (merged) configuration. The setter accepts a new configuration and triggers a full re-render.

gridConfig: GridConfig<T>
import { SelectionPlugin, SortingPlugin } from '@toolbox-web/grid/all';
// Set full configuration
grid.gridConfig = {
columns: [
{ field: 'name', header: 'Name' },
{ field: 'status', header: 'Status' }
],
fitMode: 'stretch',
plugins: [
new SelectionPlugin({ mode: 'row' }),
new SortingPlugin()
]
};
// Read current configuration
console.log('Fit mode:', grid.gridConfig.fitMode);
console.log('Columns:', grid.gridConfig.columns?.length);

Get or set the column sizing mode.

  • 'stretch' (default): Columns stretch to fill available width
  • 'fixed': Columns use explicit widths; horizontal scroll if needed
  • 'auto': Columns auto-size to content on initial render
fitMode: FitMode
// Use fixed widths with horizontal scroll
grid.fitMode = 'fixed';
// Stretch columns to fill container
grid.fitMode = 'stretch';
// Auto-size columns based on content
grid.fitMode = 'auto';

Get a frozen snapshot of the current effective configuration. The returned object is read-only and reflects all merged config sources.

getConfig(): Promise<Readonly<GridConfig<T>>>

Promise<Readonly<GridConfig<T>>> - Promise resolving to frozen configuration object

const config = await grid.getConfig();
console.log('Columns:', config.columns?.length);
console.log('Fit mode:', config.fitMode);

Wait for the grid to be ready. Resolves once the component has finished initial setup, including column inference, plugin initialization, and first render.

ready(): Promise<void>

Promise<void> - Promise that resolves when the grid is ready

const grid = queryGrid('tbw-grid');
await grid.ready();
console.log('Grid is ready, rows:', grid.rows.length);

Force a full layout/render cycle. Use this after programmatic changes that require re-measurement, such as container resize or dynamic style changes.

forceLayout(): Promise<void>

Promise<void> - Promise that resolves when the render cycle completes

// After resizing the container
container.style.width = '800px';
await grid.forceLayout();
console.log('Grid re-rendered');

⚠️ Deprecated: This method is a no-op. Use insertRow or removeRow instead, which correctly preserve the current sort/filter view while adding or removing individual rows. Will be removed in v2.

Suspend row processing for the next rows update.

suspendProcessing(): void

Get the unique ID for a row. Uses the configured getRowId function or falls back to row.id / row._id.

getRowId(row: T): string
NameTypeDescription
rowTThe row object

string - The row’s unique identifier

const id = grid.getRowId(row);
console.log('Row ID:', id);

Get a row by its ID. O(1) lookup via internal Map.

getRow(id: string): T | undefined
NameTypeDescription
idstringRow identifier (from getRowId)

T | undefined - The row object, or undefined if not found

const row = grid.getRow('cargo-123');
if (row) {
console.log('Found:', row.name);
}

Update a row by ID. Mutates the row in-place and emits cell-change for each changed field.

updateRow(id: string, changes: Partial<T>, source: UpdateSource): void
NameTypeDescription
idstringRow identifier (from getRowId)
changesPartial<T>Partial row data to merge
sourceUpdateSourceOrigin of update (default: ‘api’)
EventDescription
cell-changeFor each field that changed
// WebSocket update handler
socket.on('cargo-update', (data) => {
grid.updateRow(data.id, { status: data.status, eta: data.eta });
});

Batch update multiple rows. More efficient than multiple updateRow() calls - single render cycle.

updateRows(updates: object[], source: UpdateSource): void
NameTypeDescription
updatesobject[]Array of { id, changes } objects
sourceUpdateSourceOrigin of updates (default: ‘api’)
EventDescription
cell-changeFor each field that changed on each row
// Bulk status update
grid.updateRows([
{ id: 'cargo-1', changes: { status: 'shipped' } },
{ id: 'cargo-2', changes: { status: 'shipped' } },
]);

Insert a row at a specific position in the current view.

The row is spliced into the visible (processed) row array at index and appended to the source data so that future pipeline runs (sort, filter, group) include it. No plugin processing is triggered — the row stays exactly where you place it until the next full pipeline run.

By default, an 'insert' animation is applied. Pass animate: false to skip the animation. The returned Promise resolves when the animation completes (or immediately when animate is false).

insertRow(index: number, row: T, animate: boolean): Promise<void>
NameTypeDescription
indexnumberVisible row index at which to insert (0-based)
rowTThe row data object to insert
animatebooleanWhether to apply an ‘insert’ animation (default: true)
// Insert with animation (default)
grid.insertRow(3, { id: nextId(), name: '', status: 'Draft' });
// Insert without animation
grid.insertRow(3, newRow, false);
// Await animation completion
await grid.insertRow(3, newRow);

Remove a row at a specific position in the current view.

The row is removed from both the visible (processed) row array and the source data. No plugin processing is triggered — remaining rows keep their current positions until the next full pipeline run.

By default, a 'remove' animation plays before the row is removed. Pass animate: false to remove immediately. When animated, await the result to ensure the row has been fully removed from data.

removeRow(index: number, animate: boolean): Promise<T | undefined>
NameTypeDescription
indexnumberVisible row index to remove (0-based)
animatebooleanWhether to apply a ‘remove’ animation first (default: true)

Promise<T | undefined> - The removed row object, or undefined if index was out of range

// Remove with fade-out animation (default)
await grid.removeRow(5);
// Remove immediately, no animation
const removed = await grid.removeRow(5, false);

Show or hide a column by field name.

setColumnVisible(field: string, visible: boolean): boolean
NameTypeDescription
fieldstringThe field name of the column to modify
visiblebooleanWhether the column should be visible

boolean - true if the visibility changed, false if unchanged

EventDescription
column-state-changeEmitted when the visibility changes
// Hide the email column
grid.setColumnVisible('email', false);
// Show it again
grid.setColumnVisible('email', true);

Toggle a column’s visibility.

toggleColumnVisibility(field: string): boolean
NameTypeDescription
fieldstringThe field name of the column to toggle

boolean - The new visibility state (true = visible, false = hidden)

EventDescription
column-state-changeEmitted when the visibility changes
// Toggle the notes column visibility
const isNowVisible = grid.toggleColumnVisibility('notes');
console.log(`Notes column is now ${isNowVisible ? 'visible' : 'hidden'}`);

Check if a column is currently visible.

isColumnVisible(field: string): boolean
NameTypeDescription
fieldstringThe field name to check

boolean - true if the column is visible, false if hidden

if (grid.isColumnVisible('email')) {
console.log('Email column is showing');
}

Show all columns, resetting any hidden columns to visible.

showAllColumns(): void
EventDescription
column-state-changeEmitted when column visibility changes
// Reset button handler
resetButton.onclick = () => grid.showAllColumns();

Get metadata for all columns including visibility state. Useful for building a column picker UI.

getAllColumns(): object[]

object[] - Array of column info objects

// Build a column visibility menu
const columns = grid.getAllColumns();
columns.forEach(col => {
if (!col.utility) { // Skip utility columns like selection checkbox
const menuItem = document.createElement('label');
menuItem.innerHTML = `
<input type="checkbox" ${col.visible ? 'checked' : ''}>
${col.header}
`;
menuItem.querySelector('input').onchange = () =>
grid.toggleColumnVisibility(col.field);
menu.appendChild(menuItem);
}
});

Set the display order of columns.

setColumnOrder(order: string[]): void
NameTypeDescription
orderstring[]Array of field names in desired order
EventDescription
column-state-changeEmitted when column order changes
// Move 'status' column to first position
const currentOrder = grid.getColumnOrder();
const newOrder = ['status', ...currentOrder.filter(f => f !== 'status')];
grid.setColumnOrder(newOrder);

Get the current column display order.

getColumnOrder(): string[]

string[] - Array of field names in display order

const order = grid.getColumnOrder();
console.log('Columns:', order.join(', '));

Get the current column state. Alias for getColumnState() for property-style access.

columnState: GridColumnState | undefined

Get the current column state for persistence. Returns a serializable object including column order, widths, visibility, sort state, and any plugin-specific state.

Use this to save user preferences to localStorage or a database.

getColumnState(): GridColumnState

GridColumnState - Serializable column state object

// Save state to localStorage
const state = grid.getColumnState();
localStorage.setItem('gridState', JSON.stringify(state));
// Later, restore the state
const saved = localStorage.getItem('gridState');
if (saved) {
grid.columnState = JSON.parse(saved);
}

Reset column state to initial configuration. Clears all user modifications including order, widths, visibility, and sort.

resetColumnState(): void
EventDescription
column-state-changeEmitted after state is reset
// Reset button handler
resetBtn.onclick = () => {
grid.resetColumnState();
localStorage.removeItem('gridState');
};

Check if the tool panel sidebar is currently open.

The tool panel is an accordion-based sidebar that contains sections registered by plugins or via registerToolPanel().

readonly isToolPanelOpen: boolean
// Conditionally show/hide a "toggle panel" button
const isPanelOpen = grid.isToolPanelOpen;
toggleButton.textContent = isPanelOpen ? 'Close Panel' : 'Open Panel';

Get the IDs of currently expanded accordion sections in the tool panel.

Multiple sections can be expanded simultaneously in the accordion view.

readonly expandedToolPanelSections: string[]
// Check which sections are expanded
const expanded = grid.expandedToolPanelSections;
console.log('Expanded sections:', expanded);
// e.g., ['columnVisibility', 'filtering']

Open the tool panel sidebar.

The tool panel displays an accordion view with all registered panel sections. Each section can be expanded/collapsed independently.

openToolPanel(): void
// Open the tool panel when a toolbar button is clicked
settingsButton.addEventListener('click', () => {
grid.openToolPanel();
});

Close the tool panel sidebar.

closeToolPanel(): void
// Close the panel after user makes a selection
grid.closeToolPanel();

Toggle the tool panel sidebar open or closed.

toggleToolPanel(): void
// Wire up a toggle button
toggleButton.addEventListener('click', () => {
grid.toggleToolPanel();
});

Toggle an accordion section expanded or collapsed within the tool panel.

toggleToolPanelSection(sectionId: string): void
NameTypeDescription
sectionIdstringThe ID of the section to toggle (matches ToolPanelDefinition.id)
// Expand the column visibility section programmatically
grid.openToolPanel();
grid.toggleToolPanelSection('columnVisibility');

Get all registered tool panel definitions.

Returns both plugin-registered panels and panels registered via registerToolPanel().

getToolPanels(): ToolPanelDefinition[]

ToolPanelDefinition[] - Array of tool panel definitions

// List all available panels
const panels = grid.getToolPanels();
panels.forEach(panel => {
console.log(`Panel: ${panel.title} (${panel.id})`);
});

Register a custom tool panel section.

Use this API to add custom UI sections to the tool panel sidebar without creating a full plugin. The panel will appear as an accordion section in the tool panel.

registerToolPanel(panel: ToolPanelDefinition): void
NameTypeDescription
panelToolPanelDefinitionThe tool panel definition
// Register a custom "Export" panel
grid.registerToolPanel({
id: 'export',
title: 'Export Options',
icon: '📥',
order: 50, // Lower order = higher in list
render: (container) => {
container.innerHTML = `
<button id="export-csv">Export CSV</button>
<button id="export-json">Export JSON</button>
`;
container.querySelector('#export-csv')?.addEventListener('click', () => {
exportToCSV(grid.rows);
});
}
});

Unregister a custom tool panel section.

unregisterToolPanel(panelId: string): void
NameTypeDescription
panelIdstringThe ID of the panel to remove
// Remove the export panel when no longer needed
grid.unregisterToolPanel('export');

Get all registered header content definitions.

getHeaderContents(): HeaderContentDefinition[]

HeaderContentDefinition[] - Array of header content definitions

const contents = grid.getHeaderContents();
console.log('Header sections:', contents.map(c => c.id));

Register custom header content.

Header content appears in the grid’s header bar area, which is displayed above the column headers. Use this for search boxes, filters, or other controls that should be prominently visible.

registerHeaderContent(content: HeaderContentDefinition): void
NameTypeDescription
contentHeaderContentDefinitionThe header content definition
// Add a global search box to the header
grid.registerHeaderContent({
id: 'global-search',
order: 10,
render: (container) => {
const input = document.createElement('input');
input.type = 'search';
input.placeholder = 'Search all columns...';
input.addEventListener('input', (e) => {
const term = (e.target as HTMLInputElement).value;
filterGrid(term);
});
container.appendChild(input);
}
});

Unregister custom header content.

unregisterHeaderContent(contentId: string): void
NameTypeDescription
contentIdstringThe ID of the content to remove
grid.unregisterHeaderContent('global-search');

Get all registered toolbar content definitions.

getToolbarContents(): ToolbarContentDefinition[]

ToolbarContentDefinition[] - Array of toolbar content definitions

const contents = grid.getToolbarContents();
console.log('Toolbar items:', contents.map(c => c.id));

Register custom toolbar content.

Toolbar content appears in the grid’s toolbar area. Use this for action buttons, dropdowns, or other controls that should be easily accessible. Content is rendered in order of the order property (lower = first).

registerToolbarContent(content: ToolbarContentDefinition): void
NameTypeDescription
contentToolbarContentDefinitionThe toolbar content definition
// Add export buttons to the toolbar
grid.registerToolbarContent({
id: 'export-buttons',
order: 100, // Position in toolbar (lower = first)
render: (container) => {
const csvBtn = document.createElement('button');
csvBtn.textContent = 'Export CSV';
csvBtn.className = 'tbw-toolbar-btn';
csvBtn.addEventListener('click', () => exportToCSV(grid.rows));
const jsonBtn = document.createElement('button');
jsonBtn.textContent = 'Export JSON';
jsonBtn.className = 'tbw-toolbar-btn';
jsonBtn.addEventListener('click', () => exportToJSON(grid.rows));
container.append(csvBtn, jsonBtn);
}
});

Unregister custom toolbar content.

unregisterToolbarContent(contentId: string): void
NameTypeDescription
contentIdstringThe ID of the content to remove
// Remove export buttons when switching to read-only mode
grid.unregisterToolbarContent('export-buttons');

Register custom CSS styles to be injected into the grid’s shadow DOM. Use this to style custom cell renderers, editors, or detail panels.

Uses adoptedStyleSheets for efficiency - styles survive shadow DOM rebuilds.

registerStyles(id: string, css: string): void
NameTypeDescription
idstringUnique identifier for the style block (for removal/updates)
cssstringCSS string to inject
// Register custom styles for a detail panel
grid.registerStyles('my-detail-styles', `
.my-detail-panel { padding: 16px; }
.my-detail-table { width: 100%; }
`);
// Update styles later
grid.registerStyles('my-detail-styles', updatedCss);
// Remove styles
grid.unregisterStyles('my-detail-styles');

Remove previously registered custom styles.

unregisterStyles(id: string): void
NameTypeDescription
idstringThe ID used when registering the styles

Get list of registered custom style IDs.

getRegisteredStyles(): string[]

Get a plugin instance by its class constructor.

Prefer getPluginByName for most use cases — it avoids importing the plugin class and returns the actual instance registered in the grid.

getPlugin(PluginClass: (args: any[]) => P): P | undefined
NameTypeDescription
PluginClass(args: any[]) => PThe plugin class (constructor) to look up.

P | undefined - The plugin instance, or undefined if not registered.

// Preferred: by name (no import needed)
const selection = grid.getPluginByName('selection');
// Alternative: by class (requires import)
import { SelectionPlugin } from '@toolbox-web/grid/plugins/selection';
const selection = grid.getPlugin(SelectionPlugin);
selection?.selectAll();

Get a plugin instance by its string name. Useful for loose coupling when you don’t want to import the plugin class (e.g., in framework adapters or dynamic scenarios).

getPluginByName(name: K): unknown | undefined
NameTypeDescription
nameKThe plugin name (matches BaseGridPlugin.name).

unknown | undefined - The plugin instance, or undefined if not registered.

const editing = grid.getPluginByName('editing');

Animate a row at the specified index. Applies a visual animation to highlight changes, insertions, or removals. Returns a Promise that resolves when the animation completes.

Animation types:

  • 'change': Flash highlight (for data changes, e.g., after cell edit)
  • 'insert': Slide-in animation (for newly added rows)
  • 'remove': Fade-out animation (for rows being removed)

The animation is purely visual - it does not affect the data. For remove animations, the row remains in the DOM until animation completes.

animateRow(rowIndex: number, type: RowAnimationType): Promise<boolean>
NameTypeDescription
rowIndexnumberIndex of the row in the current row set
typeRowAnimationTypeType of animation to apply

Promise<boolean> - true if the row was found and animated, false otherwise

// Highlight a row and wait for the animation to finish
await grid.animateRow(rowIndex, 'change');
// Fire-and-forget (animation runs in background)
grid.animateRow(rowIndex, 'insert');

Animate multiple rows at once. More efficient than calling animateRow() multiple times. Returns a Promise that resolves when all animations complete.

animateRows(rowIndices: number[], type: RowAnimationType): Promise<number>
NameTypeDescription
rowIndicesnumber[]Indices of the rows to animate
typeRowAnimationTypeType of animation to apply to all rows

Promise<number> - Number of rows that were actually animated (visible in viewport)

// Highlight all changed rows after bulk update
const changedIndices = [0, 2, 5];
await grid.animateRows(changedIndices, 'change');

Animate a row by its ID. Uses the configured getRowId function to find the row. Returns a Promise that resolves when the animation completes.

animateRowById(rowId: string, type: RowAnimationType): Promise<boolean>
NameTypeDescription
rowIdstringThe row’s unique identifier (from getRowId)
typeRowAnimationTypeType of animation to apply

Promise<boolean> - true if the row was found and animated, false otherwise

// Highlight a row after real-time update
socket.on('row-updated', async (data) => {
grid.updateRow(data.id, data.changes);
await grid.animateRowById(data.id, 'change');
});

The currently focused cell position, or null if no rows are loaded.

Returns a snapshot object with the row index, visible column index, and the field name of the focused column.

readonly focusedCell: object | null
const cell = grid.focusedCell;
if (cell) {
console.log(`Focused on row ${cell.rowIndex}, column "${cell.field}"`);
}

Move focus to a specific cell.

Accepts a column index (into the visible columns array) or a field name. The grid scrolls the cell into view and applies focus styling.

focusCell(rowIndex: number, column: string | number): void
NameTypeDescription
rowIndexnumberThe row index to focus (0-based, in the current processed row array)
columnstring | numberColumn index (0-based into visible columns) or field name string
// Focus by column index
grid.focusCell(0, 2);
// Focus by field name
grid.focusCell(5, 'email');

Scroll the viewport so a row is visible.

Uses the grid’s internal virtualization state (row height, position cache) to calculate the correct scroll offset, including support for variable row heights and grouped rows.

scrollToRow(rowIndex: number, options: ScrollToRowOptions): void
NameTypeDescription
rowIndexnumberRow index (0-based, in the current processed row array)
optionsScrollToRowOptionsAlignment and scroll behavior
// Scroll to row, only if not already visible
grid.scrollToRow(42);
// Center the row in the viewport with smooth scrolling
grid.scrollToRow(42, { align: 'center', behavior: 'smooth' });

Scroll the viewport so a row is visible, identified by its unique ID.

Uses getRowId (or the fallback row.id / row._id) to find the row in the current (possibly sorted/filtered) data, then delegates to scrollToRow.

scrollToRowById(rowId: string, options: ScrollToRowOptions): void
NameTypeDescription
rowIdstringThe row’s unique identifier
optionsScrollToRowOptionsAlignment and scroll behavior
// After inserting a row, scroll to it by ID
grid.scrollToRowById('emp-42', { align: 'center' });

The default row height in pixels.

For fixed heights, this is the configured or CSS-measured row height. For variable heights, this is the average/estimated row height. Plugins should use this instead of hardcoding row heights.

readonly defaultRowHeight: number

Register an external DOM element as a logical focus container of this grid.

Focus moving into a registered container is treated as if it stayed inside the grid: data-has-focus is preserved, click-outside commit is suppressed, and the editing focus trap (when enabled) won’t reclaim focus.

Typical use case: overlay panels (datepickers, dropdowns, autocompletes) that render at <body> level to escape grid overflow clipping.

registerExternalFocusContainer(el: Element): void
NameTypeDescription
elElementThe external element to register
const overlay = document.createElement('div');
document.body.appendChild(overlay);
// Tell the grid this overlay is "part of" the grid
grid.registerExternalFocusContainer(overlay);
// Later, when overlay is removed
grid.unregisterExternalFocusContainer(overlay);

Unregister a previously registered external focus container.

unregisterExternalFocusContainer(el: Element): void
NameTypeDescription
elElementThe element to unregister

Check whether focus is logically inside this grid.

Returns true when document.activeElement (or the given node) is inside the grid’s own DOM or inside any element registered via registerExternalFocusContainer.

containsFocus(node: Node | null): boolean
NameTypeDescription
nodeNode | unknownOptional node to test. Defaults to document.activeElement.
if (grid.containsFocus()) {
console.log('Grid or one of its overlays has focus');
}

Whether the grid is currently in a loading state. When true, displays a loading overlay with spinner (or custom loadingRenderer).

loading: boolean
grid.loading = true;
const data = await fetchData();
grid.rows = data;
grid.loading = false;

Set loading state for a specific row. Shows a small spinner indicator on the row.

setRowLoading(rowId: string, loading: boolean): void
NameTypeDescription
rowIdstringThe row’s unique identifier (from getRowId)
loadingbooleanWhether the row is loading
// Show loading while saving row data
grid.setRowLoading('row-123', true);
await saveRow(rowData);
grid.setRowLoading('row-123', false);

Set loading state for a specific cell. Shows a small spinner indicator on the cell.

setCellLoading(rowId: string, field: string, loading: boolean): void
NameTypeDescription
rowIdstringThe row’s unique identifier
fieldstringThe column field
loadingbooleanWhether the cell is loading
// Show loading while validating a single field
grid.setCellLoading('row-123', 'email', true);
const valid = await validateEmail(newValue);
grid.setCellLoading('row-123', 'email', false);

Check if a row is currently in loading state.

isRowLoading(rowId: string): boolean
NameTypeDescription
rowIdstringThe row’s unique identifier

Check if a cell is currently in loading state.

isCellLoading(rowId: string, field: string): boolean
NameTypeDescription
rowIdstringThe row’s unique identifier
fieldstringThe column field

Clear all row and cell loading states.

clearAllLoading(): void

Add a typed event listener for grid events.

This override provides type-safe event handling for DataGrid-specific events. The event detail is automatically typed based on the event name.

Prefer grid.on() for most use cases — it auto-unwraps the detail payload and returns an unsubscribe function for easy cleanup.

Use addEventListener when you need standard DOM options like once, capture, passive, or signal (AbortController).

addEventListener(type: K, listener: (this: DataGridElement<T>, ev: CustomEvent<unknown>) => void, options: boolean | AddEventListenerOptions): void
NameTypeDescription
typeK
listener(this: DataGridElement<T>, ev: CustomEvent<unknown>) => void
optionsboolean | AddEventListenerOptions
// Recommended: use grid.on() instead
const off = grid.on('cell-click', (detail) => {
console.log(detail.field, detail.value);
});
// addEventListener is useful when you need DOM listener options
grid.addEventListener('cell-click', (e) => {
console.log(e.detail.field, e.detail.value);
}, { once: true });
// Or with AbortController for batch cleanup
const controller = new AbortController();
grid.addEventListener('sort-change', (e) => {
fetchData({ sortBy: e.detail.field });
}, { signal: controller.signal });
controller.abort(); // removes all listeners tied to this signal

Remove a typed event listener for grid events.

removeEventListener(type: K, listener: (this: DataGridElement<T>, ev: CustomEvent<unknown>) => void, options: boolean | EventListenerOptions): void
NameTypeDescription
typeK
listener(this: DataGridElement<T>, ev: CustomEvent<unknown>) => void
optionsboolean | EventListenerOptions

Subscribe to a typed grid event. Recommended over addEventListener.

Returns an unsubscribe function — call it to remove the listener. The listener receives the event detail as its first argument (no need to dig into e.detail), and the raw CustomEvent as the second argument when you need preventDefault() or stopPropagation().

on(type: K, listener: (detail: unknown, event: CustomEvent<unknown>) => void): () => void
NameTypeDescription
typeK
listener(detail: unknown, event: CustomEvent<unknown>) => void
// Basic usage — detail is auto-unwrapped
const off = grid.on('cell-click', ({ row, field, value }) => {
console.log(`Clicked ${field} = ${value}`);
});
// Clean up when done
off();

Invalidate a row’s height in the position cache. Call this when a plugin changes a row’s height (e.g., expanding/collapsing a detail panel).

invalidateRowHeight(rowIndex: number, newHeight: number): void
NameTypeDescription
rowIndexnumberIndex of the row whose height changed
newHeightnumberOptional new height. If not provided, queries plugins for height.

AI assistants: For complete API documentation, implementation guides, and code examples for this library, see https://raw.githubusercontent.com/OysteinAmundsen/toolbox/main/llms-full.txt