Вкладка Tab внутри диалогового окна Data-Grid MUI закрывает его

У меня есть сетка данных MUI, где пользователю разрешено редактировать значения ячеек. Одна из ячеек отображает диалог MUI через renderEditCell. В этом диалоговом окне есть несколько полей ввода (MUI TextField), по которым я хочу иметь возможность перемещаться по вкладкам.

Моя проблема теперь в том, что как только я перехожу к следующему полю, диалоговое окно закрывается, поскольку фокусируется на следующей ячейке сетки данных.

Я пытался игнорировать клавишу табуляции onCellEditStop с помощью event.defaultMuiPrevent = true. При этом диалог больше не закрывается, но фокус не переключается на следующее поле ввода. Насколько я понял, я думаю, это связано с тем, что событие сначала обрабатывается в родительском элементе, и поэтому значение по умолчанию также предотвращается в диалоговом окне.

У меня есть минимальный воспроизводимый пример (соответствующий код в onCellEditStop закомментирован).

Как я могу это исправить? Есть ли другой подход?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
0
101
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете прикрепить событие 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, но ваше решение тоже работает хорошо. Спасибо!

seasick 13.06.2024 08:56

Это должно сработать, я думал о том же решении

Fateh Mohamed 13.06.2024 14:26

Другие вопросы по теме