Skip to main content

Events reference

All event callbacks are optional props. "Before" callbacks can return false to cancel the operation.

note

The React wrapper uses onCamelCase prop names (e.g. onAfterAction) while the JS Spreadsheet API uses camelCase event names on the event bus (e.g. afterAction). See the JS API Events Reference for the imperative API.

Action events

Fired for any user action (cell edits, formatting, structural changes, etc.).

PropCancellableDescription
onBeforeActionYesFires before any user action executes. Return false to cancel. Handler: BeforeActionHandler. JS API: beforeAction.
onAfterActionNoFires after any user action completes. Handler: AfterActionHandler. JS API: afterAction.

Example: Block row deletion

import { Actions } from "@dhtmlx/trial-react-spreadsheet";

<ReactSpreadsheet
sheets={sheets}
onBeforeAction={(action, config) => {
if (action === Actions.deleteRow) return false;
}}
/>

Example: Log all user actions

<ReactSpreadsheet
sheets={sheets}
onAfterAction={(action, config) => {
console.log("Action:", action, "Cell:", config.cell);
}}
/>

Selection events

Fired when the cell selection or focus changes.

PropCancellableDescription
onBeforeSelectionSetYesFires before a cell is added to the selection. Handler: BeforeCellHandler. JS API: beforeSelectionSet.
onAfterSelectionSetNoFires after a cell is added to the selection. Handler: AfterCellHandler. JS API: afterSelectionSet.
onBeforeSelectionRemoveYesFires before a cell is removed from the selection. Handler: BeforeCellHandler.
onAfterSelectionRemoveNoFires after a cell is removed from the selection. Handler: AfterCellHandler.
onBeforeFocusSetYesFires before the focused cell changes. Handler: BeforeCellHandler. JS API: beforeFocusSet.
onAfterFocusSetNoFires after the focused cell changes. Handler: AfterCellHandler. JS API: afterFocusSet.

Example: Track selected cell

const [selectedCell, setSelectedCell] = useState<string>("");

<ReactSpreadsheet
sheets={sheets}
onAfterFocusSet={(cell) => setSelectedCell(cell)}
/>

<p>Current cell: {selectedCell}</p>

Edit events

Fired when cell editing begins or ends.

PropCancellableDescription
onBeforeEditStartYesFires before cell editing begins. Handler: BeforeEditHandler. JS API: beforeEditStart.
onAfterEditStartNoFires after cell editing begins. Handler: AfterEditHandler. JS API: afterEditStart.
onBeforeEditEndYesFires before cell editing ends. Return false to cancel and keep editing. Handler: BeforeEditHandler. JS API: beforeEditEnd.
onAfterEditEndNoFires after cell editing ends and the value is committed. Handler: AfterEditHandler. JS API: afterEditEnd.

Example: Validate before committing

<ReactSpreadsheet
sheets={sheets}
onBeforeEditEnd={(cell, value) => {
if (cell.startsWith("B") && isNaN(Number(value))) {
return false; // Cancel: column B must be numeric
}
}}
/>

Sheet events

Fired when the active sheet tab changes.

PropCancellableDescription
onBeforeSheetChangeYesFires before the active sheet changes. Handler: BeforeSheetHandler. JS API: beforeSheetChange.
onAfterSheetChangeNoFires after the active sheet changes. Handler: AfterSheetHandler. JS API: afterSheetChange.

Example: Track active sheet

<ReactSpreadsheet
sheets={sheets}
onAfterSheetChange={(sheet) => {
console.log("Switched to sheet:", sheet.name);
}}
/>

Data events

Fired when spreadsheet data is loaded.

PropDescription
onAfterDataLoadedFires after data loading completes (via sheets or loadUrl). JS API: afterDataLoaded.

Example: Show loading state

const [loading, setLoading] = useState(true);

<ReactSpreadsheet
loadUrl="/api/data"
onAfterDataLoaded={() => setLoading(false)}
/>

Input events

Fired during user input in cells or the formula bar.

PropDescription
onGroupFillFires during auto-fill (drag-fill) operations. Handler: (focusedCell: string, selectedCell: string) => void. JS API: groupFill.
onEditLineInputFires on input in the formula/edit line. Handler: (value: string) => void.
onCellInputFires on input in a cell during editing. Handler: (cell: string, value: string) => void.

Derived state callbacks

These callbacks notify about computed state changes rather than direct user actions.

PropDescription
onStateChangeNotifies when undo/redo availability changes. Handler: (state: { canUndo: boolean; canRedo: boolean }) => void.
onSearchResultsNotifies with matching cell references when the search prop is active. Handler: (cells: string[]) => void.
onFilterChangeNotifies when the user changes filters via the UI. Handler: (filter: SheetFilter) => void.

Example: Undo/redo buttons

import { useRef, useState } from "react";
import { ReactSpreadsheet, type SpreadsheetRef } from "@dhtmlx/trial-react-spreadsheet";

function App() {
const ref = useRef<SpreadsheetRef>(null);
const [history, setHistory] = useState({ canUndo: false, canRedo: false });

return (
<>
<button
disabled={!history.canUndo}
onClick={() => ref.current?.instance?.undo()}
>
Undo
</button>
<button
disabled={!history.canRedo}
onClick={() => ref.current?.instance?.redo()}
>
Redo
</button>
<ReactSpreadsheet
ref={ref}
sheets={sheets}
onStateChange={setHistory}
/>
</>
);
}

Example: Controlled search with results

const [search, setSearch] = useState<SearchConfig | undefined>();
const [results, setResults] = useState<string[]>([]);

<input
placeholder="Search..."
onChange={(e) =/> setSearch({ query: e.target.value, open: true })}
/>
<p>{results.length} cells found</p>

<ReactSpreadsheet
sheets={sheets}
search={search}
onSearchResults={setResults}
/>

Example: Sync filter state

const [activeFilter, setActiveFilter] = useState<SheetFilter | null>(null);

<ReactSpreadsheet
sheets={sheets}
onFilterChange={(filter) => setActiveFilter(filter)}
/>