Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DataGrid] Improve the handling of events (rm capture, add event, add new props) #1158

Merged
merged 22 commits into from
Mar 11, 2021
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions docs/pages/api-docs/data-grid.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,32 @@ import { DataGrid } from '@material-ui/data-grid';
| <span class="prop-name">logger</span> | <span class="prop-type">Logger</span> | null | Pass a custom logger in the components that implements the 'Logger' interface. |
| <span class="prop-name">logLevel</span> | <span class="prop-type">string | false</span> | false | Allows to pass the logging level or false to turn off logging. |
| <span class="prop-name">nonce</span> | <span class="prop-type">string</span> | | Nonce of the inline styles for [Content Security Policy](https://www.w3.org/TR/2016/REC-CSP2-20161215/#script-src-the-nonce-attribute). |
| <span class="prop-name">onCellClick</span> | <span class="prop-type">(param: GridCellParams) => void</span> | | Callback fired when a click event comes from a cell element. |
| <span class="prop-name">onCellHover</span> | <span class="prop-type">(param: GridCellParams) => void</span> | | Callback fired when a hover event comes from a cell element. |
| <span class="prop-name">onCellClick</span> | <span class="prop-type">(param: GridCellParams, event: React.MouseEvent) => void</span> | | Callback fired when a click event comes from a cell element. |
| <span class="prop-name">onCellDoubleClick</span> | <span class="prop-type">(param: GridCellParams, event: React.MouseEvent) => void</span> | | Callback fired when a double click event comes from a cell element. |
| <span class="prop-name">onCellOver</span> | <span class="prop-type">(param: GridCellParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouse over event comes from a cell element. |
| <span class="prop-name">onCellOut</span> | <span class="prop-type">(param: GridCellParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouse out comes from a cell element. |
| <span class="prop-name">onCellEnter</span> | <span class="prop-type">(param: GridCellParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouse enter event comes from a cell element. |
| <span class="prop-name">onCellLeave</span> | <span class="prop-type">(param: GridCellParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouse leave event comes from a cell element. |
| <span class="prop-name">onCellModeChange</span> | <span class="prop-type">(params: GridCellModeChangeParams) => void | | Callback fired when the cell mode changed. |
| <span class="prop-name">onColumnHeaderClick</span> | <span class="prop-type">(param: GridColParams) => void</span> | | Callback fired when a click event comes from a column header element. |
| <span class="prop-name">onColumnHeaderClick</span> | <span class="prop-type">(param: GridColParams, event: React.MouseEvent) => void</span> | | Callback fired when a click event comes from a column header element. |
| <span class="prop-name">onColumnHeaderDoubleClick</span> | <span class="prop-type">(param: GridColParams, event: React.MouseEvent) => void</span> | | Callback fired when a double click event comes from a column header element. |
| <span class="prop-name">onColumnHeaderOver</span> | <span class="prop-type">(param: GridColParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouseover event comes from a column header element. |
| <span class="prop-name">onColumnHeaderOut</span> | <span class="prop-type">(param: GridColParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouseout event comes from a column header element. |
| <span class="prop-name">onColumnHeaderEnter</span> | <span class="prop-type">(param: GridColParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouse enter event comes from a column header element. |
| <span class="prop-name">onColumnHeaderLeave</span> | <span class="prop-type">(param: GridColParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouse leave event comes from a column header element. |
| <span class="prop-name">onError</span> | <span class="prop-type">(args: any) => void</span> | | Callback fired when an exception is thrown in the grid, or when the `showError` API method is called. |
| <span class="prop-name">onEditCellChange</span> | <span class="prop-type">(params: GridEditCellParams) => void</span> | | Callback fired when the edit cell value changed. |
| <span class="prop-name">onEditCellChangeCommitted</span> | <span class="prop-type">(params: GridEditCellParams) => void</span> | | Callback fired when the cell changes are committed. |
| <span class="prop-name">onEditRowModelChange</span> | <span class="prop-type">(params: GridEditRowModelParams) => void</span> | | Callback fired when the EditRowModel changed. |
| <span class="prop-name">onFilterModelChange</span> | <span class="prop-type">(params: GridFilterModelParams) => void</span> | | Callback fired when the Filter model changes before the filters are applied. |
| <span class="prop-name">onPageChange</span> | <span class="prop-type">(param: GridPageChangeParams) => void</span> | | Callback fired when the current page has changed. |
| <span class="prop-name">onPageSizeChange</span> | <span class="prop-type">(param: GridPageChangeParams) => void</span> | | Callback fired when the page size has changed. |
| <span class="prop-name">onRowClick</span> | <span class="prop-type">(param: GridRowParams) => void</span> | | Callback fired when a click event comes from a row container element. |
| <span class="prop-name">onRowHover</span> | <span class="prop-type">(param: GridRowParams) => void</span> | | Callback fired when a hover event comes from a row container element. |
| <span class="prop-name">onRowClick</span> | <span class="prop-type">(param: GridRowParams, event: React.MouseEvent) => void</span> | | Callback fired when a click event comes from a row container element. |
| <span class="prop-name">onRowDoubleClick</span> | <span class="prop-type">(param: GridRowParams, event: React.MouseEvent) => void</span> | | Callback fired when a double click event comes from a row container element. |
| <span class="prop-name">onRowOver</span> | <span class="prop-type">(param: GridRowParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouse over comes from a row container element. |
| <span class="prop-name">onRowOut</span> | <span class="prop-type">(param: GridRowParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouse out comes from a row container element. |
| <span class="prop-name">onRowEnter</span> | <span class="prop-type">(param: GridRowParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouse enter comes from a row container element. |
| <span class="prop-name">onRowLeave</span> | <span class="prop-type">(param: GridRowParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouse leave event comes from a row container element. |
| <span class="prop-name">onRowSelected</span> | <span class="prop-type">(param: GridRowSelectedParams) => void</span> | | Callback fired when one row is selected. |
| <span class="prop-name">onSelectionModelChange</span> | <span class="prop-type">(param: GridSelectionModelChangeParams) => void</span> | | Callback fired when the selection state of one or multiple rows changes. |
| <span class="prop-name">onSortModelChange</span> | <span class="prop-type">(param: GridSortModelParams) => void</span> | | Callback fired when the sort model changes before a column is sorted. |
Expand Down
23 changes: 18 additions & 5 deletions docs/pages/api-docs/x-grid.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,32 @@ import { XGrid } from '@material-ui/x-grid';
| <span class="prop-name">logger</span> | <span class="prop-type">Logger</span> | null | Pass a custom logger in the components that implements the 'Logger' interface. |
| <span class="prop-name">logLevel</span> | <span class="prop-type">string | false</span> | false | Allows to pass the logging level or false to turn off logging. |
| <span class="prop-name">nonce</span> | <span class="prop-type">string</span> | | Nonce of the inline styles for [Content Security Policy](https://www.w3.org/TR/2016/REC-CSP2-20161215/#script-src-the-nonce-attribute). |
| <span class="prop-name">onCellClick</span> | <span class="prop-type">(param: GridCellParams) => void</span> | | Callback fired when a click event comes from a cell element. |
| <span class="prop-name">onCellHover</span> | <span class="prop-type">(param: GridCellParams) => void</span> | | Callback fired when a hover event comes from a cell element. |
| <span class="prop-name">onCellClick</span> | <span class="prop-type">(param: GridCellParams, event: React.MouseEvent) => void</span> | | Callback fired when a click event comes from a cell element. |
| <span class="prop-name">onCellDoubleClick</span> | <span class="prop-type">(param: GridCellParams, event: React.MouseEvent) => void</span> | | Callback fired when a double click event comes from a cell element. |
| <span class="prop-name">onCellOver</span> | <span class="prop-type">(param: GridCellParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouse over event comes from a cell element. |
| <span class="prop-name">onCellOut</span> | <span class="prop-type">(param: GridCellParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouse out comes from a cell element. |
| <span class="prop-name">onCellEnter</span> | <span class="prop-type">(param: GridCellParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouse enter event comes from a cell element. |
| <span class="prop-name">onCellLeave</span> | <span class="prop-type">(param: GridCellParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouse leave event comes from a cell element. |
| <span class="prop-name">onCellModeChange</span> | <span class="prop-type">(params: GridCellModeChangeParams) => void | | Callback fired when the cell mode changed. |
| <span class="prop-name">onColumnHeaderClick</span> | <span class="prop-type">(param: GridColParams) => void</span> | | Callback fired when a click event comes from a column header element. |
| <span class="prop-name">onColumnHeaderClick</span> | <span class="prop-type">(param: GridColParams, event: React.MouseEvent) => void</span> | | Callback fired when a click event comes from a column header element. |
| <span class="prop-name">onColumnHeaderDoubleClick</span> | <span class="prop-type">(param: GridColParams, event: React.MouseEvent) => void</span> | | Callback fired when a double click event comes from a column header element. |
| <span class="prop-name">onColumnHeaderOver</span> | <span class="prop-type">(param: GridColParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouseover event comes from a column header element. |
| <span class="prop-name">onColumnHeaderOut</span> | <span class="prop-type">(param: GridColParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouseout event comes from a column header element. |
| <span class="prop-name">onColumnHeaderEnter</span> | <span class="prop-type">(param: GridColParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouse enter event comes from a column header element. |
| <span class="prop-name">onColumnHeaderLeave</span> | <span class="prop-type">(param: GridColParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouse leave event comes from a column header element. |
| <span class="prop-name">onError</span> | <span class="prop-type">(args: any) => void</span> | | Callback fired when an exception is thrown in the grid, or when the `showError` API method is called. |
| <span class="prop-name">onEditCellChange</span> | <span class="prop-type">(params: GridEditCellParams) => void</span> | | Callback fired when the edit cell value changed. |
| <span class="prop-name">onEditCellChangeCommitted</span> | <span class="prop-type">(params: GridEditCellParams) => void</span> | | Callback fired when the cell changes are committed. |
| <span class="prop-name">onEditRowModelChange</span> | <span class="prop-type">(params: GridEditRowModelParams) => void</span> | | Callback fired when the EditRowModel changed. |
| <span class="prop-name">onFilterModelChange</span> | <span class="prop-type">(params: GridFilterModelParams) => void</span> | | Callback fired when the Filter model changes before the filters are applied. |
| <span class="prop-name">onPageChange</span> | <span class="prop-type">(param: GridPageChangeParams) => void</span> | | Callback fired when the current page has changed. |
| <span class="prop-name">onPageSizeChange</span> | <span class="prop-type">(param: GridPageChangeParams) => void</span> | | Callback fired when the page size has changed. |
| <span class="prop-name">onRowClick</span> | <span class="prop-type">(param: GridRowParams) => void</span> | | Callback fired when a click event comes from a row container element. |
| <span class="prop-name">onRowHover</span> | <span class="prop-type">(param: GridRowParams) => void</span> | | Callback fired when a hover event comes from a row container element. |
| <span class="prop-name">onRowClick</span> | <span class="prop-type">(param: GridRowParams, event: React.MouseEvent) => void</span> | | Callback fired when a click event comes from a row container element. |
| <span class="prop-name">onRowDoubleClick</span> | <span class="prop-type">(param: GridRowParams, event: React.MouseEvent) => void</span> | | Callback fired when a double click event comes from a row container element. |
| <span class="prop-name">onRowOver</span> | <span class="prop-type">(param: GridRowParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouse over comes from a row container element. |
| <span class="prop-name">onRowOut</span> | <span class="prop-type">(param: GridRowParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouse out comes from a row container element. |
| <span class="prop-name">onRowEnter</span> | <span class="prop-type">(param: GridRowParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouse enter comes from a row container element. |
| <span class="prop-name">onRowLeave</span> | <span class="prop-type">(param: GridRowParams, event: React.MouseEvent) => void</span> | | Callback fired when a mouse leave event comes from a row container element. |
| <span class="prop-name">onRowSelected</span> | <span class="prop-type">(param: GridRowSelectedParams) => void</span> | | Callback fired when one row is selected. |
| <span class="prop-name">onSelectionModelChange</span> | <span class="prop-type">(param: GridSelectionModelChangeParams) => void</span> | | Callback fired when the selection state of one or multiple rows changes. |
| <span class="prop-name">onSortModelChange</span> | <span class="prop-type">(param: GridSortModelParams) => void</span> | | Callback fired when the sort model changes before a column is sorted. |
Expand Down
2 changes: 2 additions & 0 deletions packages/grid/_modules_/grid/GridComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { useGridColumns } from './hooks/features/columns/useGridColumns';
import { useGridState } from './hooks/features/core/useGridState';
import { useGridPagination } from './hooks/features/pagination/useGridPagination';
import { useGridPreferencesPanel } from './hooks/features/preferencesPanel/useGridPreferencesPanel';
import { useGridParamsApi } from './hooks/features/rows/useGridParamsApi';
import { useGridRows } from './hooks/features/rows/useGridRows';
import { useGridEditRows } from './hooks/features/rows/useGridEditRows';
import { useGridSorting } from './hooks/features/sorting/useGridSorting';
Expand Down Expand Up @@ -75,6 +76,7 @@ export const GridComponent = React.forwardRef<HTMLDivElement, GridComponentProps
const onResize = useResizeContainer(apiRef);

useGridColumns(props.columns, apiRef);
useGridParamsApi(apiRef);
useGridRows(apiRef, props.rows, props.getRowId);
useGridEditRows(apiRef);
useGridKeyboard(rootContainerRef, apiRef);
Expand Down
98 changes: 69 additions & 29 deletions packages/grid/_modules_/grid/components/GridCell.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
import * as React from 'react';
import { capitalize } from '@material-ui/core/utils';
import { GridAlignment, GridCellValue } from '../models';
import * as React from 'react';
import { GRID_CELL_CSS_CLASS } from '../constants/cssClassesConstants';
import {
GRID_CELL_CLICK,
GRID_CELL_DOUBLE_CLICK,
GRID_CELL_ENTER,
GRID_CELL_LEAVE,
GRID_CELL_OUT,
GRID_CELL_OVER,
} from '../constants/eventsConstants';
import { GridAlignment, GridCellValue, GridRowId } from '../models';
import { classnames } from '../utils';
import { GridApiContext } from './GridApiContext';

export interface GridCellProps {
align: GridAlignment;
colIndex?: number;
cssClass?: string;
field?: string;
field: string;
rowId: GridRowId;
formattedValue?: GridCellValue;
hasFocus?: boolean;
height: number;
Expand All @@ -32,6 +42,7 @@ export const GridCell: React.FC<GridCellProps> = React.memo((props) => {
height,
isEditable,
rowIndex,
rowId,
showRightBorder,
tabIndex,
value,
Expand All @@ -40,53 +51,82 @@ export const GridCell: React.FC<GridCellProps> = React.memo((props) => {

const valueToRender = formattedValue || value;
const cellRef = React.useRef<HTMLDivElement>(null);
const apiRef = React.useContext(GridApiContext);

const cssClasses = classnames(
GRID_CELL_CSS_CLASS,
cssClass,
`MuiDataGrid-cell${capitalize(align)}`,
{
'MuiDataGrid-withBorder': showRightBorder,
'MuiDataGrid-cellEditable': isEditable,
},
);

React.useEffect(() => {
if (hasFocus && cellRef.current) {
cellRef.current.focus();
}
}, [hasFocus]);

const publishClick = React.useCallback(
(eventName: string) => (event: React.MouseEvent) => {
const params = apiRef!.current.getCellParams(rowId, field || '');
if (params?.colDef.disableClickEventBubbling) {
event.stopPropagation();
}
apiRef!.current.publishEvent(eventName, params, event);
},
[apiRef, field, rowId],
);

const publish = React.useCallback(
(eventName: string) => (event: React.MouseEvent) =>
apiRef!.current.publishEvent(
eventName,
apiRef!.current.getCellParams(rowId!, field || ''),
event,
),
[apiRef, field, rowId],
);

const mouseEventsHandlers = React.useMemo(
() => ({
onClick: publishClick(GRID_CELL_CLICK),
onDoubleClick: publish(GRID_CELL_DOUBLE_CLICK),
onMouseOver: publish(GRID_CELL_OVER),
onMouseOut: publish(GRID_CELL_OUT),
onMouseEnter: publish(GRID_CELL_ENTER),
onMouseLeave: publish(GRID_CELL_LEAVE),
}),
[publish, publishClick],
);

const style = {
minWidth: width,
maxWidth: width,
lineHeight: `${height - 1}px`,
minHeight: height,
maxHeight: height,
};

return (
<div
ref={cellRef}
className={classnames(GRID_CELL_CSS_CLASS, cssClass, `MuiDataGrid-cell${capitalize(align)}`, {
'MuiDataGrid-withBorder': showRightBorder,
'MuiDataGrid-cellEditable': isEditable,
})}
className={cssClasses}
role="cell"
data-value={value}
data-field={field}
data-rowindex={rowIndex}
data-editable={isEditable}
aria-colindex={colIndex}
style={{
minWidth: width,
maxWidth: width,
lineHeight: `${height - 1}px`,
minHeight: height,
maxHeight: height,
}}
style={style}
tabIndex={tabIndex}
{...mouseEventsHandlers}
>
{children || valueToRender?.toString()}
</div>
);
});

GridCell.displayName = 'GridCell';

interface EmptyCellProps {
width?: number;
height?: number;
}

export const GridLeftEmptyCell: React.FC<EmptyCellProps> = React.memo(({ width, height }) =>
!width || !height ? null : <GridCell width={width} height={height} align="left" />,
);
GridLeftEmptyCell.displayName = 'GridLeftEmptyCell';

export const GridRightEmptyCell: React.FC<EmptyCellProps> = React.memo(({ width, height }) =>
!width || !height ? null : <GridCell width={width} height={height} align="left" />,
);
GridRightEmptyCell.displayName = 'GridRightEmptyCell';
Loading