У меня есть сетка данных MUI, где пользователю разрешено редактировать значения ячеек.
Одна из ячеек отображает диалог MUI через renderEditCell
. В этом диалоговом окне есть несколько полей ввода (MUI TextField), по которым я хочу иметь возможность перемещаться по вкладкам.
Моя проблема теперь в том, что как только я перехожу к следующему полю, диалоговое окно закрывается, поскольку фокусируется на следующей ячейке сетки данных.
Я пытался игнорировать клавишу табуляции onCellEditStop
с помощью event.defaultMuiPrevent = true
. При этом диалог больше не закрывается, но фокус не переключается на следующее поле ввода. Насколько я понял, я думаю, это связано с тем, что событие сначала обрабатывается в родительском элементе, и поэтому значение по умолчанию также предотвращается в диалоговом окне.
У меня есть минимальный воспроизводимый пример (соответствующий код в onCellEditStop
закомментирован).
Как я могу это исправить? Есть ли другой подход?
Вы можете прикрепить событие onKeyDown к компоненту Dialog
и проверить, равен ли код нажатой клавиши Tab
, а затем предотвратить передачу события родительскому элементу.
onKeyDown = {(e) => {
if (e.code === "Tab") {
e.stopPropagation();
}
}}
Вот полный код:
CustomField.tsx
import Dialog from "@mui/material/Dialog";
import DialogContent from "@mui/material/DialogContent";
import TextField from "@mui/material/TextField";
import { useGridApiContext } from "@mui/x-data-grid";
import React from "react";
export default function CustomField({ id, field, row }) {
const [open, setOpen] = React.useState(true);
const apiRef = useGridApiContext();
const handleClose = () => {
setOpen(false);
apiRef.current.stopCellEditMode({ id, field });
};
return (
<Dialog
open = {open}
onClose = {handleClose}
fullWidth
maxWidth = "md"
onKeyDown = {(e) => {
if (e.code === "Tab") {
e.stopPropagation();
}
}}
>
<DialogContent>
<TextField
fullWidth
label = "Min"
name = "min"
size = "small"
sx = {{ m: 1 }}
type = "number"
defaultValue = {row.validationDef?.min || ""}
/>
<TextField
fullWidth
label = "Max"
name = "max"
size = "small"
sx = {{ m: 1 }}
type = "number"
/>
</DialogContent>
</Dialog>
);
}
App.tsx
import {
DataGrid,
GridColDef,
GridRenderEditCellParams,
} from "@mui/x-data-grid";
import Alert from "@mui/material/Alert";
import CustomField from "./CustomField";
export default function App() {
const columns: GridColDef[] = [
{
field: "attribute",
headerName: "Attribute",
editable: true,
},
{
field: "customField",
headerName: "Dialog Field",
flex: 1.5,
renderEditCell: (params: GridRenderEditCellParams) => (
<CustomField {...params} />
),
editable: true,
},
{
field: "type",
type: "singleSelect",
headerName: "Type",
editable: true,
valueOptions: [
"COMPLEX",
"BOOLEAN",
"STRING",
"NUMBER",
"DATE",
"DATETIME",
],
},
];
const rows = [
{
id: 1,
attribute: "a name",
customField: "double click me",
type: "COMPLEX",
},
];
return (
<div>
<Alert severity = "info">
<ul>
<li>Double click on the value in the "Dialog Field" column</li>
<li>Click into the first input field</li>
<li>Try to tab to the next input field</li>
</ul>
</Alert>
<DataGrid
rows = {rows}
columns = {columns}
rowHeight = {40}
hideFooter = {true}
/>
</div>
);
}
Это должно сработать, я думал о том же решении
Я надеялся найти решение, которое можно было бы применить к DataGrid, но ваше решение тоже работает хорошо. Спасибо!