Events that can be used to trigger application logic.
The ActiveGrid provides event handlers for user interactions. React to clicks, data changes, cell activation, and more.
<ActiveGrid
onRowClick={(row) => console.log('Row clicked:', row)}
onDataCommit={async (payload) => await saveData(payload)}
onCellActivate={(row, columnId) => console.log('Cell activated')}
{...}
/>(row: TData) => void<ActiveGrid
onRowClick={(row) => {
console.log('Clicked user:', row.name);
router.push(`/users/${row.id}`);
}}
{...}
/>(row: TData) => void<ActiveGrid
onRowDoubleClick={(row) => {
handleEdit(row);
}}
{...}
/>(payload: EditingCommitPayload<TData>) => Promise<void>interface EditingCommitPayload<TData> {
rowId: string;
rowIndex: number;
oldData: TData;
newData: TData;
changes: Partial<TData>;
}
<ActiveGrid
editMode="cell"
onDataCommit={async (payload) => {
console.log('Changes:', payload.changes);
try {
await api.updateUser(payload.rowId, payload.changes);
toast.success('Updated successfully');
} catch (error) {
toast.error('Update failed');
throw error; // Revert changes
}
}}
{...}
/>onDataCommit={async (payload) => {
// payload.changes = { name: 'New Name' }
await api.updateUser(payload.rowId, payload.changes);
}}onDataCommit={async (payload) => {
await api.updateUser(payload.rowId, payload.newData);
}}function UsersTable() {
const [users, setUsers] = useState<User[]>([]);
return (
<ActiveGrid
data={users}
onDataCommit={async (payload) => {
// Optimistically update UI
setUsers(prev =>
prev.map(user =>
user.id === payload.rowId ? payload.newData : user
)
);
try {
await api.updateUser(payload.rowId, payload.changes);
} catch (error) {
// Revert on error
setUsers(prev =>
prev.map(user =>
user.id === payload.rowId ? payload.oldData : user
)
);
throw error;
}
}}
{...}
/>
);
}(row: TData, columnId: string) => void(state: RowSelectionState) => voidAll table state can be controlled and observed:
'onChange' | 'onEnd''onChange'Always handle errors in async event handlers:
<ActiveGrid
onCellActivate={(row, columnId) => {
console.log(`Cell activated: ${columnId}`, row);
// Navigate to detail view
if (columnId === 'name') {
router.push(`/users/${row.id}`);
}
}}
{...}
/>import { RowSelectionState } from '@tanstack/react-table';
<ActiveGrid
onRowSelectionChange={(selection: RowSelectionState) => {
console.log('Selected rows:', Object.keys(selection));
}}
{...}
/>import { SortingState } from '@tanstack/react-table';
<ActiveGrid
onSortingChange={(sorting: SortingState) => {
console.log('Sort changed:', sorting);
}}
{...}
/>import { ColumnFiltersState } from '@tanstack/react-table';
<ActiveGrid
onColumnFiltersChange={(filters: ColumnFiltersState) => {
console.log('Filters changed:', filters);
}}
{...}
/>import { PaginationState } from '@tanstack/react-table';
<ActiveGrid
onPaginationChange={(pagination: PaginationState) => {
console.log('Page:', pagination.pageIndex);
console.log('Page size:', pagination.pageSize);
}}
{...}
/>import { ColumnVisibilityState } from '@tanstack/react-table';
<ActiveGrid
onColumnVisibilityChange={(visibility: ColumnVisibilityState) => {
console.log('Visible columns:', visibility);
}}
{...}
/>import { ColumnSizingState } from '@tanstack/react-table';
<ActiveGrid
onColumnSizingChange={(sizing: ColumnSizingState) => {
console.log('Column sizes:', sizing);
}}
{...}
/>// Update while dragging
<ActiveGrid
columnResizeMode="onChange"
onColumnSizingChange={(sizing) => {
console.log('Resizing...', sizing);
}}
{...}
/>
// Update on drag end only
<ActiveGrid
columnResizeMode="onEnd"
onColumnSizingChange={(sizing) => {
console.log('Resize complete', sizing);
}}
{...}
/>import { useState } from 'react';
import {
RowSelectionState,
SortingState,
ColumnFiltersState,
PaginationState,
} from '@tanstack/react-table';
function UsersTable() {
const [users, setUsers] = useState<User[]>([]);
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
const [sorting, setSorting] = useState<SortingState>([]);
const [filters, setFilters] = useState<ColumnFiltersState>([]);
const [pagination, setPagination] = useState<PaginationState>({
pageIndex: 0,
pageSize: 25,
});
return (
<ActiveGrid
columns={columns}
data={users}
// Row events
onRowClick={(row) => {
console.log('Row clicked:', row.id);
}}
onRowDoubleClick={(row) => {
router.push(`/users/${row.id}/edit`);
}}
// Data events
onDataCommit={async (payload) => {
try {
await api.updateUser(payload.rowId, payload.changes);
toast.success('Updated');
} catch (error) {
toast.error('Update failed');
throw error;
}
}}
// Cell events
onCellActivate={(row, columnId) => {
console.log('Cell activated:', columnId);
}}
// State change events
state={{
rowSelection,
sorting,
columnFilters: filters,
pagination,
}}
onRowSelectionChange={setRowSelection}
onSortingChange={(updater) => {
const newSorting = typeof updater === 'function'
? updater(sorting)
: updater;
console.log('Sort changed:', newSorting);
setSorting(newSorting);
}}
onColumnFiltersChange={(updater) => {
const newFilters = typeof updater === 'function'
? updater(filters)
: updater;
console.log('Filters changed:', newFilters);
setFilters(newFilters);
}}
onPaginationChange={(updater) => {
const newPagination = typeof updater === 'function'
? updater(pagination)
: updater;
console.log('Page changed:', newPagination);
setPagination(newPagination);
}}
// Resize mode
columnResizeMode="onEnd"
/>
);
}onRowClick={(row) => {
analytics.track('Row Clicked', {
userId: row.id,
userName: row.name,
});
}}onRowDoubleClick={(row) => {
router.push(`/users/${row.id}`);
}}onDataCommit={async (payload) => {
const confirmed = confirm('Save changes?');
if (!confirmed) throw new Error('Cancelled');
await api.updateUser(payload.rowId, payload.changes);
}}onDataCommit={async (payload) => {
// Validate changes
if (payload.changes.age && payload.changes.age < 18) {
toast.error('Age must be 18 or older');
throw new Error('Validation failed');
}
await api.updateUser(payload.rowId, payload.changes);
}}onDataCommit={async (payload) => {
const loadingToast = toast.loading('Saving...');
try {
await api.updateUser(payload.rowId, payload.changes);
toast.success('Saved successfully', { id: loadingToast });
} catch (error) {
toast.error('Save failed', { id: loadingToast });
throw error;
}
}}onDataCommit={async (payload) => {
try {
await api.updateUser(payload.rowId, payload.changes);
} catch (error) {
console.error('Update failed:', error);
toast.error('Update failed');
throw error; // Important: throw to revert changes
}
}}import { EditingCommitPayload } from '@workspace/active-grid';
import { SortingState, RowSelectionState } from '@tanstack/react-table';
type User = {
id: string;
name: string;
email: string;
};
const handleRowClick = (row: User) => {
console.log(row.name);
};
const handleDataCommit = async (payload: EditingCommitPayload<User>) => {
await api.updateUser(payload.rowId, payload.changes);
};
const handleSortChange = (sorting: SortingState) => {
console.log(sorting);
};
<ActiveGrid<User>
onRowClick={handleRowClick}
onDataCommit={handleDataCommit}
onSortingChange={handleSortChange}
{...}
/>