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

[docs] Add recipe for single-click editing #8365

Merged
merged 7 commits into from
Jun 16, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions docs/data/data-grid/editing/editing.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
122 changes: 122 additions & 0 deletions docs/data/data-grid/recipes-editing/SingleClickEditing.js
Original file line number Diff line number Diff line change
@@ -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 },
}),
{},
),
}),
{},
),
Comment on lines +81 to +94
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't excluding the rows/cells from the cellModesModel exit the editing mode?

In https://deploy-preview-8365--material-ui-x.netlify.app/x/react-data-grid/editing/#controlled-mode it says:

The options passed to both model props only take effect when mode changes. Updating the params of a cell or row, but keeping the same mode, makes the cell or row to stay in the same mode. Also, removing one field or row ID from the object will not cause the missing cell or row to go to "view" mode.

But I have tried removing them from the model and didn't notice any difference:
https://codesandbox.io/s/festive-raman-qz19hf?file=/demo.tsx

Copy link
Member Author

@m4theushw m4theushw May 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, only removing the row is enough if only a cell is allowed to be editable at a time. If multiple cells can be edited at the same time, then we can't remove the row. This demo implements the most broader scenario, allowing further customization.

[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 (
<div style={{ height: 300, width: '100%' }}>
<DataGrid
rows={rows}
columns={columns}
cellModesModel={cellModesModel}
onCellModesModelChange={handleCellModesModelChange}
onCellClick={handleCellClick}
/>
</div>
);
}
135 changes: 135 additions & 0 deletions docs/data/data-grid/recipes-editing/SingleClickEditing.tsx
Original file line number Diff line number Diff line change
@@ -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<GridCellModesModel>({});

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 (
<div style={{ height: 300, width: '100%' }}>
<DataGrid
rows={rows}
columns={columns}
cellModesModel={cellModesModel}
onCellModesModelChange={handleCellModesModelChange}
onCellClick={handleCellClick}
/>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<DataGrid
rows={rows}
columns={columns}
cellModesModel={cellModesModel}
onCellModesModelChange={handleCellModesModelChange}
onCellClick={handleCellClick}
/>
8 changes: 8 additions & 0 deletions docs/data/data-grid/recipes-editing/recipes-editing.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down