diff --git a/docs/data/data-grid/editing/editing.md b/docs/data/data-grid/editing/editing.md index cfd2d8ef3dea..9584ceeb2ecc 100644 --- a/docs/data/data-grid/editing/editing.md +++ b/docs/data/data-grid/editing/editing.md @@ -76,6 +76,10 @@ When a cell is in `view` mode, users can start editing a cell (or row if `editMo apiRef.current.startRowEditMode({ id: 1 }); ``` +:::info +You can also enter edit mode with a single click by following [this recipe](/x/react-data-grid/recipes-editing/#single-click-editing). +::: + ### Stop editing When a cell is in `edit` mode, the user can stop editing with any of the following interactions: diff --git a/docs/data/data-grid/recipes-editing/SingleClickEditing.js b/docs/data/data-grid/recipes-editing/SingleClickEditing.js new file mode 100644 index 000000000000..9ea1a0492057 --- /dev/null +++ b/docs/data/data-grid/recipes-editing/SingleClickEditing.js @@ -0,0 +1,122 @@ +import * as React from 'react'; +import { DataGrid, GridCellModes } from '@mui/x-data-grid'; +import { + randomCreatedDate, + randomTraderName, + randomUpdatedDate, +} from '@mui/x-data-grid-generator'; + +const columns = [ + { field: 'name', headerName: 'Name', width: 180, editable: true }, + { field: 'age', headerName: 'Age', type: 'number', editable: true }, + { + field: 'dateCreated', + headerName: 'Date Created', + type: 'date', + width: 180, + editable: true, + }, + { + field: 'lastLogin', + headerName: 'Last Login', + type: 'dateTime', + width: 220, + editable: true, + }, +]; + +const rows = [ + { + id: 1, + name: randomTraderName(), + age: 25, + dateCreated: randomCreatedDate(), + lastLogin: randomUpdatedDate(), + }, + { + id: 2, + name: randomTraderName(), + age: 36, + dateCreated: randomCreatedDate(), + lastLogin: randomUpdatedDate(), + }, + { + id: 3, + name: randomTraderName(), + age: 19, + dateCreated: randomCreatedDate(), + lastLogin: randomUpdatedDate(), + }, + { + id: 4, + name: randomTraderName(), + age: 28, + dateCreated: randomCreatedDate(), + lastLogin: randomUpdatedDate(), + }, + { + id: 5, + name: randomTraderName(), + age: 23, + dateCreated: randomCreatedDate(), + lastLogin: randomUpdatedDate(), + }, +]; + +export default function SingleClickEditing() { + const [cellModesModel, setCellModesModel] = React.useState({}); + + const handleCellClick = React.useCallback((params, event) => { + if (!params.isEditable) { + return; + } + + // Ignore portal + if (!event.currentTarget.contains(event.target)) { + return; + } + + setCellModesModel((prevModel) => { + return { + // Revert the mode of the other cells from other rows + ...Object.keys(prevModel).reduce( + (acc, id) => ({ + ...acc, + [id]: Object.keys(prevModel[id]).reduce( + (acc2, field) => ({ + ...acc2, + [field]: { mode: GridCellModes.View }, + }), + {}, + ), + }), + {}, + ), + [params.id]: { + // Revert the mode of other cells in the same row + ...Object.keys(prevModel[params.id] || {}).reduce( + (acc, field) => ({ ...acc, [field]: { mode: GridCellModes.View } }), + {}, + ), + [params.field]: { mode: GridCellModes.Edit }, + }, + }; + }); + }, []); + + const handleCellModesModelChange = React.useCallback((newModel) => { + setCellModesModel(newModel); + }, []); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/recipes-editing/SingleClickEditing.tsx b/docs/data/data-grid/recipes-editing/SingleClickEditing.tsx new file mode 100644 index 000000000000..97153fcbef66 --- /dev/null +++ b/docs/data/data-grid/recipes-editing/SingleClickEditing.tsx @@ -0,0 +1,135 @@ +import * as React from 'react'; +import { + DataGrid, + GridCellModes, + GridCellModesModel, + GridCellParams, + GridRowsProp, + GridColDef, +} from '@mui/x-data-grid'; +import { + randomCreatedDate, + randomTraderName, + randomUpdatedDate, +} from '@mui/x-data-grid-generator'; + +const columns: GridColDef[] = [ + { field: 'name', headerName: 'Name', width: 180, editable: true }, + { field: 'age', headerName: 'Age', type: 'number', editable: true }, + { + field: 'dateCreated', + headerName: 'Date Created', + type: 'date', + width: 180, + editable: true, + }, + { + field: 'lastLogin', + headerName: 'Last Login', + type: 'dateTime', + width: 220, + editable: true, + }, +]; + +const rows: GridRowsProp = [ + { + id: 1, + name: randomTraderName(), + age: 25, + dateCreated: randomCreatedDate(), + lastLogin: randomUpdatedDate(), + }, + { + id: 2, + name: randomTraderName(), + age: 36, + dateCreated: randomCreatedDate(), + lastLogin: randomUpdatedDate(), + }, + { + id: 3, + name: randomTraderName(), + age: 19, + dateCreated: randomCreatedDate(), + lastLogin: randomUpdatedDate(), + }, + { + id: 4, + name: randomTraderName(), + age: 28, + dateCreated: randomCreatedDate(), + lastLogin: randomUpdatedDate(), + }, + { + id: 5, + name: randomTraderName(), + age: 23, + dateCreated: randomCreatedDate(), + lastLogin: randomUpdatedDate(), + }, +]; + +export default function SingleClickEditing() { + const [cellModesModel, setCellModesModel] = React.useState({}); + + const handleCellClick = React.useCallback( + (params: GridCellParams, event: React.MouseEvent) => { + if (!params.isEditable) { + return; + } + + // Ignore portal + if (!event.currentTarget.contains(event.target as Element)) { + return; + } + + setCellModesModel((prevModel) => { + return { + // Revert the mode of the other cells from other rows + ...Object.keys(prevModel).reduce( + (acc, id) => ({ + ...acc, + [id]: Object.keys(prevModel[id]).reduce( + (acc2, field) => ({ + ...acc2, + [field]: { mode: GridCellModes.View }, + }), + {}, + ), + }), + {}, + ), + [params.id]: { + // Revert the mode of other cells in the same row + ...Object.keys(prevModel[params.id] || {}).reduce( + (acc, field) => ({ ...acc, [field]: { mode: GridCellModes.View } }), + {}, + ), + [params.field]: { mode: GridCellModes.Edit }, + }, + }; + }); + }, + [], + ); + + const handleCellModesModelChange = React.useCallback( + (newModel: GridCellModesModel) => { + setCellModesModel(newModel); + }, + [], + ); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/recipes-editing/SingleClickEditing.tsx.preview b/docs/data/data-grid/recipes-editing/SingleClickEditing.tsx.preview new file mode 100644 index 000000000000..e4ad0002f8de --- /dev/null +++ b/docs/data/data-grid/recipes-editing/SingleClickEditing.tsx.preview @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/recipes-editing/recipes-editing.md b/docs/data/data-grid/recipes-editing/recipes-editing.md index 5af7d6cc1b03..30e93b5b796c 100644 --- a/docs/data/data-grid/recipes-editing/recipes-editing.md +++ b/docs/data/data-grid/recipes-editing/recipes-editing.md @@ -98,6 +98,14 @@ Note that the `onCellEditStart` and `onCellEditStop` props also have to be used {{"demo": "LinkedFieldsCellEditing.js", "bg": "inline", "defaultCodeOpen": false}} +## Single click editing + +By default, one of the ways to [enter the edit mode](/x/react-data-grid/editing/#start-editing) is by double-clicking a cell. +Using the [controlled mode](/x/react-data-grid/editing/#controlled-model) and listening to click events, you can also enter the edit mode with just a single click. +The following demo implements this behavior. + +{{"demo": "SingleClickEditing.js", "bg": "inline", "defaultCodeOpen": false}} + ## Usage with `@mui/x-date-pickers` By default, the data grid uses native browser inputs for editing `date` and `dateTime` columns.