Row Data

Row data is the array of objects that populates the grid. Each object in the array becomes one row, and the grid's column definitions determine which properties are displayed.

Setting Row Data

At Initialization

Pass row data through the grid config:

const engine = createGrid({
  columns: [{ field: 'name' }, { field: 'age' }],
  rowData: [
    { name: 'Alice', age: 30 },
    { name: 'Bob', age: 25 },
  ],
});

After Initialization

Update row data at any time through the API:

api.setRowData([
  { name: 'Alice', age: 31 },
  { name: 'Bob', age: 26 },
  { name: 'Carol', age: 28 },
]);

In React, pass rowData as a prop. The adapter syncs changes automatically:

<GridStorm columns={columns} rowData={data} />

:::note Calling setRowData() replaces the entire dataset. It clears the current selection and reprocesses all rows through the filter/sort pipeline. :::

Row Nodes

Internally, GridStorm wraps each data object in a RowNode. A RowNode tracks metadata needed for rendering and interaction:

interface RowNode<TData> {
  id: string;               // Unique identifier
  data: TData | undefined;  // Your data object (undefined for group rows)
  sourceIndex: number;       // Index in the original data array
  displayIndex: number;      // Index in the displayed (post-filter/sort) list
  level: number;             // Nesting level (0 = top level)
  rowHeight: number;         // Height in pixels
  rowTop: number;            // Vertical offset for virtual scroll
  parent: RowNode | null;    // Parent group node
  children: RowNode[] | null;// Child rows (for group nodes)
  expanded: boolean;         // Is this group expanded?
  group: boolean;            // Is this a group row?
  groupField: string | null; // Which field is this grouped by?
  groupValue: any;           // The group key value
  leafChildrenCount: number; // Count of leaf descendants
  aggData: Record<string, any> | null; // Aggregated values
  selected: boolean;         // Is this row selected?
  selectable: boolean;       // Can this row be selected?
  rowPinned: 'top' | 'bottom' | null; // Pinned row position
  version: number;           // Change counter for re-rendering
}

Accessing Row Nodes

Retrieve a single row node by ID:

const node = api.getRowNode('row-123');

Iterate over all row nodes:

api.forEachNode((node, index) => {
  console.log(node.id, node.data);
});

Get a displayed row by its visible index:

const node = api.getDisplayedRowAtIndex(0); // first visible row

Get the total displayed count (after filters):

const count = api.getDisplayedRowCount();

Row IDs

By default, GridStorm generates row IDs from the array index ("0", "1", "2", ...). For datasets where rows have a natural unique key, provide a getRowId function:

const engine = createGrid({
  columns: [...],
  rowData: employees,
  getRowId: (params) => params.data.employeeId,
});

:::tip Always provide getRowId when your data has a natural unique identifier. This ensures correct behavior when:

The getRowId callback receives:

interface GetRowIdParams<TData> {
  data: TData;         // The row data object
  index: number;       // Array index
  parentKeys?: string[]; // Parent group keys (for grouped data)
}

Row Height

Fixed Row Height

Set a uniform row height (default is 40 pixels):

const engine = createGrid({
  columns: [...],
  rowData: [...],
  rowHeight: 48,
});

Dynamic Row Height

Provide a function to compute row height per row:

const engine = createGrid({
  columns: [...],
  rowData: [...],
  rowHeight: (params) => {
    return params.data.hasNotes ? 80 : 40;
  },
});

Pinned Rows

Pin rows to the top or bottom of the grid so they remain visible during scrolling:

const engine = createGrid({
  columns: [...],
  rowData: employees,
  pinnedTopRowData: [{ name: 'TOTAL', age: null }],
  pinnedBottomRowData: [{ name: 'Average', age: 32 }],
});

Pinned rows are excluded from sorting, filtering, and pagination. They always display at their designated position.

Updating Individual Cells

While setRowData() replaces the entire dataset, you can update individual cells by modifying the data object on a row node and refreshing:

const node = api.getRowNode('emp-123');
if (node && node.data) {
  node.data.salary = 75000;
  node.version++;
  api.refreshCells({ rowIds: ['emp-123'], colIds: ['salary'] });
}

:::caution Mutating node.data directly bypasses the command bus. For auditable state changes, dispatch an editing command instead. :::

Performance with Large Datasets

GridStorm is designed to handle large datasets efficiently:

For datasets with 100,000+ rows, ensure you provide a getRowId function so GridStorm can efficiently match rows across updates.

Next Steps