Skip to content

Commit

Permalink
[docs] Add paragraph about managing focus of custom edit components
Browse files Browse the repository at this point in the history
  • Loading branch information
m4theushw committed Jul 12, 2023
1 parent 4f136ba commit de9cc14
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 14 deletions.
14 changes: 8 additions & 6 deletions docs/data/data-grid/editing/CustomEditComponent.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import Rating from '@mui/material/Rating';
import { unstable_useEnhancedEffect as useEnhancedEffect } from '@mui/utils';
import { DataGrid, useGridApiContext } from '@mui/x-data-grid';

function renderRating(params) {
return <Rating readOnly value={params.value} />;
}

function RatingEditInputCell(props) {
const { id, value, field } = props;
const { id, value, field, hasFocus } = props;
const apiRef = useGridApiContext();
const ref = React.useRef();

const handleChange = (event, newValue) => {
apiRef.current.setEditCellValue({ id, field, value: newValue });
};

const handleRef = (element) => {
if (element) {
const input = element.querySelector(`input[value="${value}"]`);
useEnhancedEffect(() => {
if (hasFocus && ref.current) {
const input = ref.current.querySelector(`input[value="${value}"]`);
input?.focus();
}
};
}, [hasFocus, value]);

return (
<Box sx={{ display: 'flex', alignItems: 'center', pr: 2 }}>
<Rating
ref={handleRef}
ref={ref}
name="rating"
precision={1}
value={value}
Expand Down
14 changes: 8 additions & 6 deletions docs/data/data-grid/editing/CustomEditComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import Rating from '@mui/material/Rating';
import { unstable_useEnhancedEffect as useEnhancedEffect } from '@mui/utils';
import {
DataGrid,
GridRenderCellParams,
Expand All @@ -13,26 +14,27 @@ function renderRating(params: GridRenderCellParams<any, number>) {
}

function RatingEditInputCell(props: GridRenderCellParams<any, number>) {
const { id, value, field } = props;
const { id, value, field, hasFocus } = props;
const apiRef = useGridApiContext();
const ref = React.useRef<HTMLElement>();

const handleChange = (event: React.SyntheticEvent, newValue: number | null) => {
apiRef.current.setEditCellValue({ id, field, value: newValue });
};

const handleRef = (element: HTMLSpanElement) => {
if (element) {
const input = element.querySelector<HTMLInputElement>(
useEnhancedEffect(() => {
if (hasFocus && ref.current) {
const input = ref.current.querySelector<HTMLInputElement>(
`input[value="${value}"]`,
);
input?.focus();
}
};
}, [hasFocus, value]);

return (
<Box sx={{ display: 'flex', alignItems: 'center', pr: 2 }}>
<Rating
ref={handleRef}
ref={ref}
name="rating"
precision={1}
value={value}
Expand Down
16 changes: 14 additions & 2 deletions docs/data/data-grid/editing/editing.md
Original file line number Diff line number Diff line change
Expand Up @@ -362,17 +362,29 @@ Once a new value is entered into the input, it must be sent to the data grid.
To do this, pass the row ID, the column field, and the new cell value to a call to `apiRef.current.setEditCellValue`.
The new value will be parsed and validated, and the `value` prop will reflect the changes in the next render.

It's important to also handle the [accessibility](/x/react-data-grid/accessibility/) of custom edit components.
When a cell enters edit mode, an element must be focused to provide access via keyboard and for screen readers.
Since multiple cells may be in edit mode at the same time, the `hasFocus` prop will be `true` on the cell that should have focus.
Use this prop to focus the appropriate element.

```tsx
function CustomEditComponent(props: GridRenderEditCellParams) {
const { id, value, field } = props;
const { id, value, field, hasFocus } = props;
const apiRef = useGridApiContext();
const ref = React.useRef();

React.useLayoutEffect(() => {
if (hasFocus) {
ref.current.focus();
}
}, [hasFocus]);

const handleValueChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const newValue = event.target.value; // The new value entered by the user
apiRef.current.setEditCellValue({ id, field, value: newValue });
};

return <input type="text" value={value} onChange={handleValueChange} />;
return <input ref={ref} type="text" value={value} onChange={handleValueChange} />;
}
```

Expand Down

0 comments on commit de9cc14

Please sign in to comment.