DataGrid Component Reference

The main data grid component.

<script>
  import { DataGrid } from 'svelte-datagrid';
</script>

<DataGrid {data} {columns} />

Props

Data Props

PropTypeDescription
dataTData[]Array of row data objects. Either data or dataSource must be provided.
dataSourceDataSource<TData>Custom DataSource for server-side data. Either data or dataSource must be provided.
columnsColumnDef<TData>[]Column definitions (required)

Layout Props

PropTypeDefaultDescription
heightnumber \| string400Grid height. Number = px, string = CSS value
widthnumber \| string'100%'Grid width. Number = px, string = CSS value
rowHeightnumber40Height of each data row in pixels
headerHeightnumber48Height of the header row in pixels
overscannumber5Number of rows to render outside visible area

Feature Props

PropTypeDefaultDescription
selectableboolean \| 'single' \| 'multiple'falseEnable row selection
filterablebooleanfalseShow per-column filter inputs
searchablebooleanfalseShow global search bar
resizablebooleanfalseEnable column resizing
reorderablebooleanfalseEnable column reordering via drag-and-drop
sortablebooleantrueEnable column sorting (can be overridden per-column)
editablebooleanfalseEnable cell editing (can be overridden per-column)

Auto-Save Behavior

When editable is enabled and the DataSource implements MutableDataSource, edits are automatically persisted:

<script>
  import { DataGrid } from 'svelte-datagrid';

  let data = [
    { id: 1, name: 'Alice', email: 'alice@example.com' },
    { id: 2, name: 'Bob', email: 'bob@example.com' }
  ];

  const columns = [
    { key: 'id', header: 'ID', width: 60, editable: false },
    { key: 'name', header: 'Name', width: 150 },
    { key: 'email', header: 'Email', width: 200 }
  ];
</script>

<DataGrid
  {data}
  {columns}
  editable
  getRowId={(row) => row.id}
/>

Identification Props

PropTypeDefaultDescription
getRowId(row: TData, index: number) => string \| number(_, i) => iFunction to get unique row identifier

State Props

PropTypeDefaultDescription
loadingbooleanfalseShow loading indicator
emptyMessagestring'No data to display'Message when data is empty
errorMessagestring \| undefinedundefinedError message (shows error state when set)

Styling Props

PropTypeDefaultDescription
classstring''CSS class for grid container
rowClassstring \| ((row: TData, index: number) => string)undefinedCSS class for data rows

Bindable Props

PropTypeDescription
gridStateGridStateBind to access grid state API
<DataGrid {data} {columns} bind:gridState />

<script>
  let gridState;
  // Now you can call gridState.selectAll(), gridState.navigateToFirst(), etc.
</script>

Events

Selection Events

EventPayloadDescription
onselectionchange{ selected: Set, added: (string\|number)[], removed: (string\|number)[] }Selection changed
<DataGrid
  {data}
  {columns}
  selectable="multiple"
  onselectionchange={(e) => {
    console.log('Selected IDs:', e.selected);
    console.log('Added:', e.added);
    console.log('Removed:', e.removed);
  }}
/>

Row/Cell Events

EventPayloadDescription
onrowclick{ row: TData, rowIndex: number, event: MouseEvent }Row clicked
oncellclick{ row: TData, column: ColumnDef, value: unknown, rowIndex: number, event: MouseEvent }Cell clicked
<DataGrid
  {data}
  {columns}
  oncellclick={(e) => console.log(`Clicked ${e.column.key}: ${e.value}`)}
/>

Sort Events

EventPayloadDescription
onSortChangeSortSpec[]Sort configuration changed
<DataGrid
  {data}
  {columns}
  onSortChange={(sort) => {
    console.log('Sort:', sort);
    // [{ field: 'name', direction: 'asc' }]
  }}
/>

Edit Events

EventPayloadDescription
oncelleditGridCellEditEvent<TData>Cell value was edited
oncellvalidate(rowId, columnKey, value) => string \| nullValidate cell value before commit
<DataGrid
  {data}
  {columns}
  editable
  oncelledit={(e) => {
    console.log(`Edited ${e.columnKey}: ${e.oldValue} -> ${e.newValue}`);
  }}
  oncellvalidate={(rowId, columnKey, value) => {
    if (columnKey === 'email' && !value?.includes('@')) {
      return 'Invalid email address';
    }
    return null;
  }}
/>

Column Events

EventPayloadDescription
oncolumnresize{ column: string, width: number }Column resized

Snippets

Override default displays with snippets:

loadingSnippet

Custom loading indicator:

<DataGrid {data} {columns} loading>
  {#snippet loadingSnippet()}
    <div class="spinner">Loading...</div>
  {/snippet}
</DataGrid>

emptySnippet

Custom empty state:

<DataGrid {data} {columns}>
  {#snippet emptySnippet()}
    <div class="empty">
      <p>No results found</p>
      <button onclick={clearFilters}>Clear Filters</button>
    </div>
  {/snippet}
</DataGrid>

errorSnippet

Custom error display:

<DataGrid {data} {columns} errorMessage={error}>
  {#snippet errorSnippet(message)}
    <div class="error">
      <h3>Error</h3>
      <p>{message}</p>
      <button onclick={retry}>Retry</button>
    </div>
  {/snippet}
</DataGrid>

Accessibility

The component implements the ARIA grid pattern:

ElementAttributeValue
Containerrolegrid
Containeraria-rowcountTotal row count
Containeraria-colcountColumn count
Header rowrolerow
Header cellsrolecolumnheader
Bodyrolerowgroup
Data rowsrolerow
Data rowsaria-rowindexRow position
Data cellsrolegridcell
Selected rowsaria-selectedtrue

Example

<script lang="ts">
  import { DataGrid } from 'svelte-datagrid';

  interface User {
    id: number;
    name: string;
    email: string;
    active: boolean;
  }

  const data: User[] = [
    { id: 1, name: 'Alice', email: 'alice@example.com', active: true },
    { id: 2, name: 'Bob', email: 'bob@example.com', active: false }
  ];

  const columns = [
    { key: 'id', header: 'ID', width: 60 },
    { key: 'name', header: 'Name', width: 150 },
    { key: 'email', header: 'Email', width: 200 },
    { key: 'active', header: 'Active', width: 80 }
  ];

  let gridState;
  let selectedIds = new Set<number>();

  function handleSelection(event) {
    selectedIds = event.selected;
  }
</script>

<div style="height: 400px;">
  <DataGrid
    {data}
    {columns}
    selectable="multiple"
    filterable
    searchable
    resizable
    getRowId={(row) => row.id}
    onselectionchange={handleSelection}
    bind:gridState
  />
</div>

<p>Selected: {selectedIds.size} rows</p>

See also