0
# Event Handling
1
2
The event handling system provides comprehensive callbacks for user interactions with cells, rows, columns, and grid controls. All events provide detailed parameter objects with context and grid API access.
3
4
## Capabilities
5
6
### Cell Events
7
8
Event handlers for cell-level user interactions including clicks and hover events.
9
10
```typescript { .api }
11
interface CellParams {
12
/** The HTMLElement that triggered the event */
13
element?: HTMLElement;
14
/** The column field of the cell that triggered the event */
15
field: string;
16
/** The cell value */
17
value: CellValue;
18
/** A function that lets you get data from other columns */
19
getValue: (field: string) => CellValue;
20
/** The full set of data of the row that the current cell belongs to */
21
data: RowData;
22
/** The row model of the row that the current cell belongs to */
23
rowModel: RowModel;
24
/** The column of the row that the current cell belongs to */
25
colDef: any;
26
/** The row index of the row that the current cell belongs to */
27
rowIndex: number;
28
/** ApiRef that lets you manipulate the grid */
29
api: any;
30
}
31
32
interface GridOptions {
33
/** Handler for cell click events */
34
onCellClick?: (param: CellParams) => void;
35
/** Handler for cell hover events */
36
onCellHover?: (param: CellParams) => void;
37
}
38
```
39
40
**Usage Examples:**
41
42
```typescript
43
import React from "react";
44
import { DataGrid, CellParams } from "@material-ui/data-grid";
45
46
function CellEventGrid() {
47
const handleCellClick = (params: CellParams) => {
48
console.log("Cell clicked:", {
49
rowId: params.id,
50
field: params.field,
51
value: params.value,
52
formattedValue: params.formattedValue,
53
});
54
55
// Access full row data
56
console.log("Full row:", params.row);
57
58
// Access column definition
59
console.log("Column config:", params.colDef);
60
61
// Perform actions based on column
62
if (params.field === "actions") {
63
handleActionClick(params.row);
64
}
65
};
66
67
const handleCellHover = (params: CellParams) => {
68
// Show tooltip or highlight related data
69
if (params.field === "status") {
70
showStatusTooltip(params.value, params.formattedValue);
71
}
72
};
73
74
const handleActionClick = (row: RowData) => {
75
console.log("Action clicked for row:", row.id);
76
// Navigate to edit page or open modal
77
};
78
79
const showStatusTooltip = (value: CellValue, formattedValue: CellValue) => {
80
console.log(`Status: ${formattedValue} (raw: ${value})`);
81
};
82
83
return (
84
<div style={{ height: 600, width: "100%" }}>
85
<DataGrid
86
rows={rows}
87
columns={columns}
88
onCellClick={handleCellClick}
89
onCellHover={handleCellHover}
90
/>
91
</div>
92
);
93
}
94
```
95
96
### Row Events
97
98
Event handlers for row-level interactions including clicks, hover, and selection.
99
100
```typescript { .api }
101
interface RowParams {
102
/** Row identifier */
103
id: RowId;
104
/** Array of all column definitions */
105
columns: Columns;
106
/** Complete row data object */
107
row: RowData;
108
/** Grid API reference */
109
api: GridApi;
110
}
111
112
interface RowSelectedParams {
113
/** Row identifier */
114
id: RowId;
115
/** Complete row data object */
116
row: RowData;
117
/** Current selection state */
118
isSelected: boolean;
119
/** Grid API reference */
120
api: GridApi;
121
}
122
123
interface SelectionChangeParams {
124
/** Array of selected row IDs (max 1 in community edition) */
125
selectionModel: RowId[];
126
/** Grid API reference */
127
api: GridApi;
128
}
129
130
interface GridOptions {
131
/** Handler for row click events */
132
onRowClick?: (param: RowParams) => void;
133
/** Handler for row hover events */
134
onRowHover?: (param: RowParams) => void;
135
/** Handler for individual row selection changes */
136
onRowSelected?: (param: RowSelectedParams) => void;
137
/** Handler for overall selection state changes */
138
onSelectionChange?: (param: SelectionChangeParams) => void;
139
}
140
```
141
142
**Usage Examples:**
143
144
```typescript
145
import React from "react";
146
import {
147
DataGrid,
148
RowParams,
149
RowSelectedParams,
150
SelectionChangeParams
151
} from "@material-ui/data-grid";
152
153
function RowEventGrid() {
154
const [selectedRows, setSelectedRows] = React.useState<RowId[]>([]);
155
const [hoveredRow, setHoveredRow] = React.useState<RowId | null>(null);
156
157
const handleRowClick = (params: RowParams) => {
158
console.log("Row clicked:", params.id);
159
console.log("Row data:", params.row);
160
161
// Navigate to detail view
162
navigateToDetails(params.id);
163
};
164
165
const handleRowHover = (params: RowParams) => {
166
setHoveredRow(params.id);
167
168
// Show preview or additional info
169
showRowPreview(params.row);
170
};
171
172
const handleRowSelected = (params: RowSelectedParams) => {
173
console.log(`Row ${params.id} ${params.isSelected ? 'selected' : 'deselected'}`);
174
175
if (params.isSelected) {
176
// Perform action when row is selected
177
loadRelatedData(params.row);
178
}
179
};
180
181
const handleSelectionChange = (params: SelectionChangeParams) => {
182
setSelectedRows(params.selectionModel);
183
184
console.log("Total selected:", params.selectionModel.length);
185
186
// Update UI based on selection
187
if (params.selectionModel.length > 0) {
188
showBulkActions(true);
189
} else {
190
showBulkActions(false);
191
}
192
};
193
194
const navigateToDetails = (rowId: RowId) => {
195
console.log(`Navigating to details for row ${rowId}`);
196
};
197
198
const showRowPreview = (row: RowData) => {
199
console.log("Preview for:", row.name);
200
};
201
202
const loadRelatedData = (row: RowData) => {
203
console.log("Loading related data for:", row.id);
204
};
205
206
const showBulkActions = (show: boolean) => {
207
console.log(`Bulk actions ${show ? 'shown' : 'hidden'}`);
208
};
209
210
return (
211
<div style={{ height: 600, width: "100%" }}>
212
<DataGrid
213
rows={rows}
214
columns={columns}
215
checkboxSelection
216
onRowClick={handleRowClick}
217
onRowHover={handleRowHover}
218
onRowSelected={handleRowSelected}
219
onSelectionChange={handleSelectionChange}
220
/>
221
<div>
222
Selected rows: {selectedRows.length}
223
{hoveredRow && <span> | Hovering: {hoveredRow}</span>}
224
</div>
225
</div>
226
);
227
}
228
```
229
230
### Column Events
231
232
Event handlers for column header interactions and sorting changes.
233
234
```typescript { .api }
235
interface ColParams {
236
/** Column field name */
237
field: string;
238
/** Column definition object */
239
colDef: ColDef;
240
/** Grid API reference */
241
api: GridApi;
242
}
243
244
interface SortModelParams {
245
/** Current sort configuration */
246
sortModel: SortModel[];
247
/** Grid API reference */
248
api: GridApi;
249
}
250
251
interface SortModel {
252
/** Column field to sort by */
253
field: string;
254
/** Sort direction */
255
sort: SortDirection;
256
}
257
258
interface GridOptions {
259
/** Handler for column header click events */
260
onColumnHeaderClick?: (param: ColParams) => void;
261
/** Handler for sort model changes */
262
onSortModelChange?: (params: SortModelParams) => void;
263
}
264
265
type SortDirection = "asc" | "desc" | null;
266
```
267
268
**Usage Examples:**
269
270
```typescript
271
import React from "react";
272
import {
273
DataGrid,
274
ColParams,
275
SortModelParams,
276
SortModel
277
} from "@material-ui/data-grid";
278
279
function ColumnEventGrid() {
280
const [sortModel, setSortModel] = React.useState<SortModel[]>([]);
281
282
const handleColumnHeaderClick = (params: ColParams) => {
283
console.log("Column header clicked:", params.field);
284
console.log("Column definition:", params.colDef);
285
286
// Show column menu or custom actions
287
if (params.field === "status") {
288
showStatusFilter(params.colDef);
289
}
290
};
291
292
const handleSortModelChange = (params: SortModelParams) => {
293
setSortModel(params.sortModel);
294
295
console.log("Sort changed:", params.sortModel);
296
297
// Handle server-side sorting
298
if (params.sortModel.length > 0) {
299
const sort = params.sortModel[0];
300
fetchSortedData(sort.field, sort.sort);
301
} else {
302
fetchSortedData(null, null);
303
}
304
};
305
306
const showStatusFilter = (colDef: ColDef) => {
307
console.log("Showing filter for status column:", colDef.headerName);
308
};
309
310
const fetchSortedData = (field: string | null, direction: SortDirection) => {
311
console.log(`Fetching data sorted by ${field} ${direction}`);
312
// Implement server-side sorting
313
};
314
315
return (
316
<div style={{ height: 600, width: "100%" }}>
317
<DataGrid
318
rows={rows}
319
columns={columns}
320
sortModel={sortModel}
321
sortingMode="server"
322
onColumnHeaderClick={handleColumnHeaderClick}
323
onSortModelChange={handleSortModelChange}
324
/>
325
<div>
326
Current sort: {sortModel.length > 0
327
? `${sortModel[0].field} ${sortModel[0].sort}`
328
: 'none'}
329
</div>
330
</div>
331
);
332
}
333
```
334
335
### Pagination Events
336
337
Event handlers for pagination control interactions and state changes.
338
339
```typescript { .api }
340
interface PageChangeParams {
341
/** New page number (1-based) */
342
page: number;
343
/** Current page size */
344
pageSize: number;
345
/** Grid API reference */
346
api: GridApi;
347
}
348
349
interface GridOptions {
350
/** Handler for page number changes */
351
onPageChange?: (param: PageChangeParams) => void;
352
/** Handler for page size changes */
353
onPageSizeChange?: (param: PageChangeParams) => void;
354
}
355
```
356
357
**Usage Examples:**
358
359
```typescript
360
import React from "react";
361
import { DataGrid, PageChangeParams } from "@material-ui/data-grid";
362
363
function PaginationEventGrid() {
364
const [page, setPage] = React.useState(1);
365
const [pageSize, setPageSize] = React.useState(25);
366
const [loading, setLoading] = React.useState(false);
367
368
const handlePageChange = (params: PageChangeParams) => {
369
console.log("Page changed to:", params.page);
370
setPage(params.page);
371
372
// Load new page data
373
fetchPageData(params.page, params.pageSize);
374
};
375
376
const handlePageSizeChange = (params: PageChangeParams) => {
377
console.log("Page size changed to:", params.pageSize);
378
setPageSize(params.pageSize);
379
setPage(1); // Reset to first page
380
381
// Load data with new page size
382
fetchPageData(1, params.pageSize);
383
};
384
385
const fetchPageData = async (pageNum: number, pageSizeNum: number) => {
386
setLoading(true);
387
try {
388
const response = await fetch(
389
`/api/data?page=${pageNum}&pageSize=${pageSizeNum}`
390
);
391
const data = await response.json();
392
// Update rows with new data
393
console.log("Loaded page data:", data);
394
} finally {
395
setLoading(false);
396
}
397
};
398
399
return (
400
<div style={{ height: 600, width: "100%" }}>
401
<DataGrid
402
rows={rows}
403
columns={columns}
404
loading={loading}
405
pagination={true}
406
page={page}
407
pageSize={pageSize}
408
paginationMode="server"
409
rowCount={1000} // Total rows from server
410
onPageChange={handlePageChange}
411
onPageSizeChange={handlePageSizeChange}
412
/>
413
<div>
414
Page {page}, showing {pageSize} rows per page
415
</div>
416
</div>
417
);
418
}
419
```
420
421
### Error Events
422
423
Event handlers for error states and error recovery.
424
425
```typescript { .api }
426
interface GridOptions {
427
/** Handler for grid errors and exceptions */
428
onError?: (args: any) => void;
429
}
430
```
431
432
**Usage Examples:**
433
434
```typescript
435
import React from "react";
436
import { DataGrid } from "@material-ui/data-grid";
437
438
function ErrorHandlingGrid() {
439
const [error, setError] = React.useState<string | null>(null);
440
441
const handleError = (args: any) => {
442
console.error("Grid error:", args);
443
444
// Display user-friendly error message
445
if (args.message) {
446
setError(args.message);
447
} else {
448
setError("An unexpected error occurred in the data grid");
449
}
450
451
// Report error to logging service
452
reportError(args);
453
};
454
455
const reportError = (error: any) => {
456
// Send error to monitoring service
457
console.log("Reporting error to service:", error);
458
};
459
460
const clearError = () => {
461
setError(null);
462
};
463
464
return (
465
<div style={{ height: 600, width: "100%" }}>
466
{error && (
467
<div style={{
468
background: "#ffebee",
469
color: "#c62828",
470
padding: "10px",
471
marginBottom: "10px",
472
borderRadius: "4px"
473
}}>
474
<strong>Error:</strong> {error}
475
<button onClick={clearError} style={{ marginLeft: "10px" }}>
476
Dismiss
477
</button>
478
</div>
479
)}
480
<DataGrid
481
rows={rows}
482
columns={columns}
483
onError={handleError}
484
error={error} // Pass error to grid for display
485
/>
486
</div>
487
);
488
}
489
```
490
491
### Event Combination Patterns
492
493
Common patterns for combining multiple event handlers.
494
495
```typescript
496
import React from "react";
497
import {
498
DataGrid,
499
CellParams,
500
RowParams,
501
SelectionChangeParams
502
} from "@material-ui/data-grid";
503
504
function CombinedEventGrid() {
505
const [selectedRows, setSelectedRows] = React.useState<RowId[]>([]);
506
const [lastAction, setLastAction] = React.useState<string>("");
507
508
// Coordinated event handling
509
const handleCellClick = (params: CellParams) => {
510
setLastAction(`Cell clicked: ${params.field} in row ${params.id}`);
511
512
// Don't trigger row click for action cells
513
if (params.field === "actions") {
514
return; // Cell event handled, don't bubble to row
515
}
516
};
517
518
const handleRowClick = (params: RowParams) => {
519
setLastAction(`Row clicked: ${params.id}`);
520
521
// Only select if no rows currently selected
522
if (selectedRows.length === 0) {
523
// Programmatically select via API
524
params.api.selectRow(params.id);
525
}
526
};
527
528
const handleSelectionChange = (params: SelectionChangeParams) => {
529
setSelectedRows(params.selectionModel);
530
531
if (params.selectionModel.length > 0) {
532
setLastAction(`Row selected: ${params.selectionModel[0]}`);
533
} else {
534
setLastAction("Selection cleared");
535
}
536
};
537
538
return (
539
<div style={{ height: 600, width: "100%" }}>
540
<DataGrid
541
rows={rows}
542
columns={columns}
543
checkboxSelection
544
onCellClick={handleCellClick}
545
onRowClick={handleRowClick}
546
onSelectionChange={handleSelectionChange}
547
/>
548
<div style={{ marginTop: "10px" }}>
549
<strong>Last action:</strong> {lastAction}
550
</div>
551
<div>
552
<strong>Selected:</strong> {selectedRows.join(", ") || "None"}
553
</div>
554
</div>
555
);
556
}
557
```
558
559
### Event Performance Considerations
560
561
```typescript
562
// ✅ Good: Debounce expensive operations
563
import { debounce } from "@material-ui/data-grid";
564
565
const debouncedCellHover = React.useMemo(
566
() => debounce((params: CellParams) => {
567
// Expensive operation like API call
568
fetchCellDetails(params.id, params.field);
569
}, 300),
570
[]
571
);
572
573
// ✅ Good: Use useCallback for event handlers
574
const handleCellClick = React.useCallback((params: CellParams) => {
575
// Handler logic
576
}, [/* dependencies */]);
577
578
// ✅ Good: Prevent unnecessary re-renders
579
const MemoizedGrid = React.memo(() => {
580
const eventHandlers = React.useMemo(() => ({
581
onCellClick: handleCellClick,
582
onRowClick: handleRowClick,
583
onSelectionChange: handleSelectionChange,
584
}), [handleCellClick, handleRowClick, handleSelectionChange]);
585
586
return <DataGrid {...eventHandlers} rows={rows} columns={columns} />;
587
});
588
```