CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-material-ui--data-grid

Community edition React data grid component with sorting, filtering, pagination, and Material-UI integration

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

event-handling.mddocs/

Event Handling

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.

Capabilities

Cell Events

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>
  );
}

Row Events

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>
  );
}

Column Events

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>
  );
}

Pagination Events

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>
  );
}

Error Events

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>
  );
}

Event Combination Patterns

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>
  );
}

Event Performance Considerations

// ✅ 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} />;
});

docs

api-reference.md

column-system.md

configuration-options.md

data-grid-component.md

event-handling.md

index.md

row-management.md

tile.json