# EventProps

> _Since v0.7.0_

Event handler props for grid events.
All handlers receive the unwrapped detail as first argument,
with optional access to the full CustomEvent for preventDefault().

## Properties

| Property | Type | Description |
| -------- | ---- | ----------- |
| `onCellClick?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/api/core/interfaces/cellclickdetail/">CellClickDetail</a>&lt;TRow&gt;&gt;</code> | Fired when a cell is clicked. |
| `onRowClick?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/api/core/interfaces/rowclickdetail/">RowClickDetail</a>&lt;TRow&gt;&gt;</code> | Fired when a row is clicked. |
| `onCellActivate?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/api/core/interfaces/cellactivatedetail/">CellActivateDetail</a>&lt;TRow&gt;&gt;</code> | Fired when a cell is activated (Enter key or double-click). |
| `onCellChange?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/api/core/interfaces/cellchangedetail/">CellChangeDetail</a>&lt;TRow&gt;&gt;</code> | Fired when a cell value changes (before commit). |
| `onCellCommit?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/editing/interfaces/cellcommitdetail/">CellCommitDetail</a>&lt;TRow&gt;&gt;</code> | Fired when a cell edit is committed. Cancelable - call `event.preventDefault()` to reject the edit. |
| `onRowCommit?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/editing/interfaces/rowcommitdetail/">RowCommitDetail</a>&lt;TRow&gt;&gt;</code> | Fired when all pending row edits are committed. |
| `onChangedRowsReset?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/editing/interfaces/changedrowsresetdetail/">ChangedRowsResetDetail</a>&lt;TRow&gt;&gt;</code> | Fired when changed rows cache is reset via `resetChangedRows()`. |
| `onEditOpen?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/editing/interfaces/editopendetail/">EditOpenDetail</a>&lt;TRow&gt;&gt;</code> | Fired when an editor opens for a cell. |
| `onBeforeEditClose?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/editing/interfaces/beforeeditclosedetail/">BeforeEditCloseDetail</a>&lt;TRow&gt;&gt;</code> | Fired before an editor closes (commit or cancel). Cancelable. |
| `onEditClose?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/editing/interfaces/editclosedetail/">EditCloseDetail</a>&lt;TRow&gt;&gt;</code> | Fired after an editor closes (commit or cancel). |
| `onCellCancel?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/editing/interfaces/cellcanceldetail/">CellCancelDetail</a>&gt;</code> | Fired when a cell edit is canceled (e.g. Escape key). |
| `onDirtyChange?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/editing/interfaces/dirtychangedetail/">DirtyChangeDetail</a>&lt;TRow&gt;&gt;</code> | Fired when the dirty/changed-rows state transitions. |
| `onDataChange?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/api/core/interfaces/datachangedetail/">DataChangeDetail</a>&gt;</code> | Fired when the row data is replaced (e.g. via the `data` property setter). |
| `onSortChange?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/api/core/interfaces/sortchangedetail/">SortChangeDetail</a>&gt;</code> | Fired when sort state changes. |
| `onFilterChange?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/filtering/interfaces/filterchangedetail/">FilterChangeDetail</a>&gt;</code> | Fired when filter values change. |
| `onColumnResize?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/api/core/interfaces/columnresizedetail/">ColumnResizeDetail</a>&gt;</code> | Fired when a column is resized. |
| `onColumnMove?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/reorder-columns/interfaces/columnmovedetail/">ColumnMoveDetail</a>&gt;</code> | Fired when a column is moved via drag-and-drop. Cancelable - call `event.preventDefault()` to cancel the move. |
| `onColumnResizeReset?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/api/core/interfaces/columnresizeresetdetail/">ColumnResizeResetDetail</a>&gt;</code> | Fired when a column resize is reset (e.g. via double-click on the resize handle). |
| `onColumnVisibility?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/visibility/interfaces/columnvisibilitydetail/">ColumnVisibilityDetail</a>&gt;</code> | Fired when a column is shown or hidden — either via the visibility sidebar, `grid.toggleColumnVisibility(field)`, `grid.setColumnVisible(field, visible)`, or `grid.showAllColumns()`. |
| `onColumnStateChange?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/api/core/interfaces/gridcolumnstate/">GridColumnState</a>&gt;</code> | Fired when column state changes (resize, reorder, visibility). Useful for persisting column state. |
| `onSelectionChange?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/selection/interfaces/selectionchangedetail/">SelectionChangeDetail</a>&gt;</code> | Fired when selection changes. |
| `onRowMove?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/row-drag-drop/interfaces/rowmovedetail/">RowMoveDetail</a>&lt;TRow&gt;&gt;</code> | Fired when a row is moved via drag-and-drop. Cancelable - call `event.preventDefault()` to cancel the move. |
| `onRowDragStart?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/row-drag-drop/interfaces/rowdragstartdetail/">RowDragStartDetail</a>&lt;TRow&gt;&gt;</code> | Fired when a row drag starts. Cancelable. |
| `onRowDragEnd?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/row-drag-drop/interfaces/rowdragenddetail/">RowDragEndDetail</a>&lt;TRow&gt;&gt;</code> | Fired when a row drag ends (after drop or cancel). |
| `onRowDrop?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/row-drag-drop/interfaces/rowdropdetail/">RowDropDetail</a>&lt;TRow&gt;&gt;</code> | Fired on the target grid when rows are dropped from another grid. Cancelable. |
| `onRowTransfer?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/row-drag-drop/interfaces/rowtransferdetail/">RowTransferDetail</a>&lt;TRow&gt;&gt;</code> | Fired on BOTH source and target grids after a successful cross-grid row transfer. |
| `onGroupToggle?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/grouping-rows/interfaces/grouptoggledetail/">GroupToggleDetail</a>&gt;</code> | Fired when a group is expanded or collapsed. |
| `onGroupExpand?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/grouping-rows/interfaces/groupexpanddetail/">GroupExpandDetail</a>&gt;</code> | Fired when a group is expanded. |
| `onGroupCollapse?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/grouping-rows/interfaces/groupcollapsedetail/">GroupCollapseDetail</a>&gt;</code> | Fired when a group is collapsed. |
| `onContextMenuOpen?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/context-menu/interfaces/contextmenuopendetail/">ContextMenuOpenDetail</a>&gt;</code> | Fired when the context menu opens. |
| `onTreeExpand?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/tree/interfaces/treeexpanddetail/">TreeExpandDetail</a>&lt;TRow&gt;&gt;</code> | Fired when a tree node is expanded. |
| `onDetailExpand?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/master-detail/interfaces/detailexpanddetail/">DetailExpandDetail</a>&gt;</code> | Fired when a detail panel is expanded or collapsed. |
| `onResponsiveChange?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/responsive/interfaces/responsivechangedetail/">ResponsiveChangeDetail</a>&gt;</code> | Fired when responsive mode changes (table ↔ card). |
| `onCopy?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/clipboard/interfaces/copydetail/">CopyDetail</a>&gt;</code> | Fired when cells are copied to clipboard. |
| `onPaste?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/clipboard/interfaces/pastedetail/">PasteDetail</a>&gt;</code> | Fired when cells are pasted from clipboard. |
| `onUndo?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/undo-redo/interfaces/undoredodetail/">UndoRedoDetail</a>&gt;</code> | Fired when an undo action is performed. |
| `onRedo?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/undo-redo/interfaces/undoredodetail/">UndoRedoDetail</a>&gt;</code> | Fired when a redo action is performed. |
| `onExportComplete?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/export/interfaces/exportcompletedetail/">ExportCompleteDetail</a>&gt;</code> | Fired when export completes. |
| `onPrintStart?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/print/interfaces/printstartdetail/">PrintStartDetail</a>&gt;</code> | Fired when print starts. |
| `onPrintComplete?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/plugins/print/interfaces/printcompletedetail/">PrintCompleteDetail</a>&gt;</code> | Fired when print completes. |
| `onTbwScroll?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/api/core/interfaces/tbwscrolldetail/">TbwScrollDetail</a>&gt;</code> | Fired (rAF-batched) when the grid's viewport scrolls vertically. |
| `onRender?` | <code><a href="/grid/react/api/types/eventhandler/">EventHandler</a>&lt;<a href="/grid/api/core/interfaces/renderdetail/">RenderDetail</a>&gt;</code> | Fired once at the end of every render-scheduler flush, after all plugin `afterRender` hooks have run and `ready()` has resolved. |

### Property Details

#### onCellClick

```tsx
onCellClick={(detail) => console.log('Clicked:', detail.field, detail.value)}
```

---

#### onRowClick

```tsx
onRowClick={(detail) => navigateTo(`/employees/${detail.row.id}`)}
```

---

#### onCellActivate

```tsx
onCellActivate={(detail) => openEditor(detail.field, detail.row)}
```

---

#### onCellChange

```tsx
onCellChange={(detail) => validateChange(detail)}
```

---

#### onCellCommit

```tsx
onCellCommit={(detail, event) => {
  if (!isValid(detail.value)) {
    event?.preventDefault();
    showError('Invalid value');
  }
}}
```

---

#### onRowCommit

```tsx
onRowCommit={(detail) => saveToServer(detail.row)}
```

---

#### onChangedRowsReset

```tsx
onChangedRowsReset={(detail) => console.log('Reset:', detail.rows.length, 'rows cleared')}
```

---

#### onSortChange

```tsx
onSortChange={(detail) => console.log('Sort:', detail.field, detail.direction)}
```

---

#### onFilterChange

```tsx
onFilterChange={(detail) => console.log('Filters:', detail.activeFilters)}
```

---

#### onColumnResize

```tsx
onColumnResize={(detail) => console.log('Resized:', detail.field, detail.width)}
```

---

#### onColumnMove

```tsx
onColumnMove={(detail, event) => {
  if (detail.column.field === 'id') {
    event?.preventDefault(); // Don't allow moving ID column
  }
}}
```

---

#### onColumnResizeReset

```tsx
onColumnResizeReset={(detail) => console.log('Reset width for:', detail.field)}
```

---

#### onColumnVisibility

Fired when a column is shown or hidden — either via the visibility
sidebar, `grid.toggleColumnVisibility(field)`, `grid.setColumnVisible(field, visible)`,
or `grid.showAllColumns()`.

`field` and `visible` are present for single-column toggles and
`undefined` for bulk operations (`showAllColumns`). `visibleColumns`
always lists the current set.

```tsx
onColumnVisibility={(detail) => {
  console.log(detail.hidden ? 'Hidden:' : 'Shown:', detail.field);
  localStorage.setItem('visibleColumns', JSON.stringify(detail.visibleColumns));
}}
```

---

#### onColumnStateChange

```tsx
onColumnStateChange={(state) => saveToLocalStorage('gridState', state)}
```

---

#### onSelectionChange

```tsx
onSelectionChange={(detail) => {
  console.log('Selected ranges:', detail.ranges);
  console.log('Mode:', detail.mode);
}}
```

---

#### onRowMove

```tsx
onRowMove={(detail, event) => {
  if (!canMove(detail.row)) {
    event?.preventDefault();
  }
}}
```

---

#### onGroupToggle

```tsx
onGroupToggle={(detail) => {
  console.log(detail.expanded ? 'Expanded' : 'Collapsed', detail.key);
}}
```

---

#### onTreeExpand

```tsx
onTreeExpand={(detail) => console.log('Expanded:', detail.row)}
```

---

#### onDetailExpand

```tsx
onDetailExpand={(detail) => {
  if (detail.expanded) loadDetailData(detail.rowId);
}}
```

---

#### onResponsiveChange

```tsx
onResponsiveChange={(detail) => {
  console.log('Mode:', detail.mode); // 'table' | 'card'
}}
```

---

#### onCopy

```tsx
onCopy={(detail) => console.log('Copied:', detail.text)}
```

---

#### onPaste

```tsx
onPaste={(detail) => console.log('Pasted:', detail.affectedCells.length, 'cells')}
```

---

#### onUndo

```tsx
onUndo={(detail) => console.log('Undid:', detail.action.type, '- Can undo:', detail.canUndo)}
```

---

#### onRedo

```tsx
onRedo={(detail) => console.log('Redid:', detail.action.type, '- Can redo:', detail.canRedo)}
```

---

#### onExportComplete

```tsx
onExportComplete={(detail) => console.log('Exported:', detail.filename)}
```

---

#### onPrintStart

```tsx
onPrintStart={(detail) => console.log('Printing:', detail.rowCount, 'rows')}
```

---

#### onPrintComplete

```tsx
onPrintComplete={() => console.log('Print complete')}
```

---

#### onTbwScroll

Fired (rAF-batched) when the grid's viewport scrolls vertically.

For server-side pagination of large datasets prefer `ServerSidePlugin`
— this event is the lower-level primitive for custom load-more
triggers, deferring heavy cell content, dismissing overlays, etc.

```tsx
onTbwScroll={(detail) => {
  if (detail.scrollTop + detail.clientHeight >= detail.scrollHeight - 200) {
    loadMore();
  }
}}
```

---

#### onRender

Fired once at the end of every render-scheduler flush, after all
plugin `afterRender` hooks have run and `ready()` has resolved.

Use this to act on the rendered DOM after a programmatic mutation
(e.g. focus the first input of a freshly added row in full-grid
edit mode) without `setTimeout` or double-`requestAnimationFrame`
hacks. Fires on every flush — including scroll-driven virtual-window
updates — so prefer subscribing once and unsubscribing (or gating on
`detail.phase >= RenderPhase.ROWS`) when you only care about a
specific mutation.

```tsx
onRender={(detail) => {
  if (detail.initial) console.log('first render complete');
}}
```

---
