Community edition React data grid component with sorting, filtering, pagination, and Material-UI integration
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
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.
Event handlers for cell-level user interactions including clicks and hover events.
interface CellParams {
/** The HTMLElement that triggered the event */
element?: HTMLElement;
/** The column field of the cell that triggered the event */
field: string;
/** The cell value */
value: CellValue;
/** A function that lets you get data from other columns */
getValue: (field: string) => CellValue;
/** The full set of data of the row that the current cell belongs to */
data: RowData;
/** The row model of the row that the current cell belongs to */
rowModel: RowModel;
/** The column of the row that the current cell belongs to */
colDef: any;
/** The row index of the row that the current cell belongs to */
rowIndex: number;
/** ApiRef that lets you manipulate the grid */
api: any;
}
interface GridOptions {
/** Handler for cell click events */
onCellClick?: (param: CellParams) => void;
/** Handler for cell hover events */
onCellHover?: (param: CellParams) => void;
}Usage Examples:
import React from "react";
import { DataGrid, CellParams } from "@material-ui/data-grid";
function CellEventGrid() {
const handleCellClick = (params: CellParams) => {
console.log("Cell clicked:", {
rowId: params.id,
field: params.field,
value: params.value,
formattedValue: params.formattedValue,
});
// Access full row data
console.log("Full row:", params.row);
// Access column definition
console.log("Column config:", params.colDef);
// Perform actions based on column
if (params.field === "actions") {
handleActionClick(params.row);
}
};
const handleCellHover = (params: CellParams) => {
// Show tooltip or highlight related data
if (params.field === "status") {
showStatusTooltip(params.value, params.formattedValue);
}
};
const handleActionClick = (row: RowData) => {
console.log("Action clicked for row:", row.id);
// Navigate to edit page or open modal
};
const showStatusTooltip = (value: CellValue, formattedValue: CellValue) => {
console.log(`Status: ${formattedValue} (raw: ${value})`);
};
return (
<div style={{ height: 600, width: "100%" }}>
<DataGrid
rows={rows}
columns={columns}
onCellClick={handleCellClick}
onCellHover={handleCellHover}
/>
</div>
);
}Event handlers for row-level interactions including clicks, hover, and selection.
interface RowParams {
/** Row identifier */
id: RowId;
/** Array of all column definitions */
columns: Columns;
/** Complete row data object */
row: RowData;
/** Grid API reference */
api: GridApi;
}
interface RowSelectedParams {
/** Row identifier */
id: RowId;
/** Complete row data object */
row: RowData;
/** Current selection state */
isSelected: boolean;
/** Grid API reference */
api: GridApi;
}
interface SelectionChangeParams {
/** Array of selected row IDs (max 1 in community edition) */
selectionModel: RowId[];
/** Grid API reference */
api: GridApi;
}
interface GridOptions {
/** Handler for row click events */
onRowClick?: (param: RowParams) => void;
/** Handler for row hover events */
onRowHover?: (param: RowParams) => void;
/** Handler for individual row selection changes */
onRowSelected?: (param: RowSelectedParams) => void;
/** Handler for overall selection state changes */
onSelectionChange?: (param: SelectionChangeParams) => void;
}Usage Examples:
import React from "react";
import {
DataGrid,
RowParams,
RowSelectedParams,
SelectionChangeParams
} from "@material-ui/data-grid";
function RowEventGrid() {
const [selectedRows, setSelectedRows] = React.useState<RowId[]>([]);
const [hoveredRow, setHoveredRow] = React.useState<RowId | null>(null);
const handleRowClick = (params: RowParams) => {
console.log("Row clicked:", params.id);
console.log("Row data:", params.row);
// Navigate to detail view
navigateToDetails(params.id);
};
const handleRowHover = (params: RowParams) => {
setHoveredRow(params.id);
// Show preview or additional info
showRowPreview(params.row);
};
const handleRowSelected = (params: RowSelectedParams) => {
console.log(`Row ${params.id} ${params.isSelected ? 'selected' : 'deselected'}`);
if (params.isSelected) {
// Perform action when row is selected
loadRelatedData(params.row);
}
};
const handleSelectionChange = (params: SelectionChangeParams) => {
setSelectedRows(params.selectionModel);
console.log("Total selected:", params.selectionModel.length);
// Update UI based on selection
if (params.selectionModel.length > 0) {
showBulkActions(true);
} else {
showBulkActions(false);
}
};
const navigateToDetails = (rowId: RowId) => {
console.log(`Navigating to details for row ${rowId}`);
};
const showRowPreview = (row: RowData) => {
console.log("Preview for:", row.name);
};
const loadRelatedData = (row: RowData) => {
console.log("Loading related data for:", row.id);
};
const showBulkActions = (show: boolean) => {
console.log(`Bulk actions ${show ? 'shown' : 'hidden'}`);
};
return (
<div style={{ height: 600, width: "100%" }}>
<DataGrid
rows={rows}
columns={columns}
checkboxSelection
onRowClick={handleRowClick}
onRowHover={handleRowHover}
onRowSelected={handleRowSelected}
onSelectionChange={handleSelectionChange}
/>
<div>
Selected rows: {selectedRows.length}
{hoveredRow && <span> | Hovering: {hoveredRow}</span>}
</div>
</div>
);
}Event handlers for column header interactions and sorting changes.
interface ColParams {
/** Column field name */
field: string;
/** Column definition object */
colDef: ColDef;
/** Grid API reference */
api: GridApi;
}
interface SortModelParams {
/** Current sort configuration */
sortModel: SortModel[];
/** Grid API reference */
api: GridApi;
}
interface SortModel {
/** Column field to sort by */
field: string;
/** Sort direction */
sort: SortDirection;
}
interface GridOptions {
/** Handler for column header click events */
onColumnHeaderClick?: (param: ColParams) => void;
/** Handler for sort model changes */
onSortModelChange?: (params: SortModelParams) => void;
}
type SortDirection = "asc" | "desc" | null;Usage Examples:
import React from "react";
import {
DataGrid,
ColParams,
SortModelParams,
SortModel
} from "@material-ui/data-grid";
function ColumnEventGrid() {
const [sortModel, setSortModel] = React.useState<SortModel[]>([]);
const handleColumnHeaderClick = (params: ColParams) => {
console.log("Column header clicked:", params.field);
console.log("Column definition:", params.colDef);
// Show column menu or custom actions
if (params.field === "status") {
showStatusFilter(params.colDef);
}
};
const handleSortModelChange = (params: SortModelParams) => {
setSortModel(params.sortModel);
console.log("Sort changed:", params.sortModel);
// Handle server-side sorting
if (params.sortModel.length > 0) {
const sort = params.sortModel[0];
fetchSortedData(sort.field, sort.sort);
} else {
fetchSortedData(null, null);
}
};
const showStatusFilter = (colDef: ColDef) => {
console.log("Showing filter for status column:", colDef.headerName);
};
const fetchSortedData = (field: string | null, direction: SortDirection) => {
console.log(`Fetching data sorted by ${field} ${direction}`);
// Implement server-side sorting
};
return (
<div style={{ height: 600, width: "100%" }}>
<DataGrid
rows={rows}
columns={columns}
sortModel={sortModel}
sortingMode="server"
onColumnHeaderClick={handleColumnHeaderClick}
onSortModelChange={handleSortModelChange}
/>
<div>
Current sort: {sortModel.length > 0
? `${sortModel[0].field} ${sortModel[0].sort}`
: 'none'}
</div>
</div>
);
}Event handlers for pagination control interactions and state changes.
interface PageChangeParams {
/** New page number (1-based) */
page: number;
/** Current page size */
pageSize: number;
/** Grid API reference */
api: GridApi;
}
interface GridOptions {
/** Handler for page number changes */
onPageChange?: (param: PageChangeParams) => void;
/** Handler for page size changes */
onPageSizeChange?: (param: PageChangeParams) => void;
}Usage Examples:
import React from "react";
import { DataGrid, PageChangeParams } from "@material-ui/data-grid";
function PaginationEventGrid() {
const [page, setPage] = React.useState(1);
const [pageSize, setPageSize] = React.useState(25);
const [loading, setLoading] = React.useState(false);
const handlePageChange = (params: PageChangeParams) => {
console.log("Page changed to:", params.page);
setPage(params.page);
// Load new page data
fetchPageData(params.page, params.pageSize);
};
const handlePageSizeChange = (params: PageChangeParams) => {
console.log("Page size changed to:", params.pageSize);
setPageSize(params.pageSize);
setPage(1); // Reset to first page
// Load data with new page size
fetchPageData(1, params.pageSize);
};
const fetchPageData = async (pageNum: number, pageSizeNum: number) => {
setLoading(true);
try {
const response = await fetch(
`/api/data?page=${pageNum}&pageSize=${pageSizeNum}`
);
const data = await response.json();
// Update rows with new data
console.log("Loaded page data:", data);
} finally {
setLoading(false);
}
};
return (
<div style={{ height: 600, width: "100%" }}>
<DataGrid
rows={rows}
columns={columns}
loading={loading}
pagination={true}
page={page}
pageSize={pageSize}
paginationMode="server"
rowCount={1000} // Total rows from server
onPageChange={handlePageChange}
onPageSizeChange={handlePageSizeChange}
/>
<div>
Page {page}, showing {pageSize} rows per page
</div>
</div>
);
}Event handlers for error states and error recovery.
interface GridOptions {
/** Handler for grid errors and exceptions */
onError?: (args: any) => void;
}Usage Examples:
import React from "react";
import { DataGrid } from "@material-ui/data-grid";
function ErrorHandlingGrid() {
const [error, setError] = React.useState<string | null>(null);
const handleError = (args: any) => {
console.error("Grid error:", args);
// Display user-friendly error message
if (args.message) {
setError(args.message);
} else {
setError("An unexpected error occurred in the data grid");
}
// Report error to logging service
reportError(args);
};
const reportError = (error: any) => {
// Send error to monitoring service
console.log("Reporting error to service:", error);
};
const clearError = () => {
setError(null);
};
return (
<div style={{ height: 600, width: "100%" }}>
{error && (
<div style={{
background: "#ffebee",
color: "#c62828",
padding: "10px",
marginBottom: "10px",
borderRadius: "4px"
}}>
<strong>Error:</strong> {error}
<button onClick={clearError} style={{ marginLeft: "10px" }}>
Dismiss
</button>
</div>
)}
<DataGrid
rows={rows}
columns={columns}
onError={handleError}
error={error} // Pass error to grid for display
/>
</div>
);
}Common patterns for combining multiple event handlers.
import React from "react";
import {
DataGrid,
CellParams,
RowParams,
SelectionChangeParams
} from "@material-ui/data-grid";
function CombinedEventGrid() {
const [selectedRows, setSelectedRows] = React.useState<RowId[]>([]);
const [lastAction, setLastAction] = React.useState<string>("");
// Coordinated event handling
const handleCellClick = (params: CellParams) => {
setLastAction(`Cell clicked: ${params.field} in row ${params.id}`);
// Don't trigger row click for action cells
if (params.field === "actions") {
return; // Cell event handled, don't bubble to row
}
};
const handleRowClick = (params: RowParams) => {
setLastAction(`Row clicked: ${params.id}`);
// Only select if no rows currently selected
if (selectedRows.length === 0) {
// Programmatically select via API
params.api.selectRow(params.id);
}
};
const handleSelectionChange = (params: SelectionChangeParams) => {
setSelectedRows(params.selectionModel);
if (params.selectionModel.length > 0) {
setLastAction(`Row selected: ${params.selectionModel[0]}`);
} else {
setLastAction("Selection cleared");
}
};
return (
<div style={{ height: 600, width: "100%" }}>
<DataGrid
rows={rows}
columns={columns}
checkboxSelection
onCellClick={handleCellClick}
onRowClick={handleRowClick}
onSelectionChange={handleSelectionChange}
/>
<div style={{ marginTop: "10px" }}>
<strong>Last action:</strong> {lastAction}
</div>
<div>
<strong>Selected:</strong> {selectedRows.join(", ") || "None"}
</div>
</div>
);
}// ✅ Good: Debounce expensive operations
import { debounce } from "@material-ui/data-grid";
const debouncedCellHover = React.useMemo(
() => debounce((params: CellParams) => {
// Expensive operation like API call
fetchCellDetails(params.id, params.field);
}, 300),
[]
);
// ✅ Good: Use useCallback for event handlers
const handleCellClick = React.useCallback((params: CellParams) => {
// Handler logic
}, [/* dependencies */]);
// ✅ Good: Prevent unnecessary re-renders
const MemoizedGrid = React.memo(() => {
const eventHandlers = React.useMemo(() => ({
onCellClick: handleCellClick,
onRowClick: handleRowClick,
onSelectionChange: handleSelectionChange,
}), [handleCellClick, handleRowClick, handleSelectionChange]);
return <DataGrid {...eventHandlers} rows={rows} columns={columns} />;
});