MUI DataGrid 单选值

jro*_*004 5 reactjs material-ui

所以我试图避免构建自己的选择,只想将类型设置为 singleSelect。所以我已经到达了选择渲染的位置,并且当我双击单元格时有一些选项。我遇到的两个问题是我不确定如何设置选择哪个选项,当我单击一个选项时,我收到一个错误A component is changing an uncontrolled input to be controlled. 我见过的所有文档都显示您的选项是简单字符串。

\n

列定义

\n
const columns: GridColDef[] = [\n  \xe2\x80\xa6\n  {\n    field: \xe2\x80\x98payment\xe2\x80\x99,\n    flex: 1,\n    editable: true,\n    type: \xe2\x80\x98singleSelect\xe2\x80\x99,\n    getOptionLabel: (value: any) => value.name,\n    getOptionValue: (value: any) => value.id,\n    valueOptions: (params: GridValueOptionsParams<TMyProps>) => {\n      const options = params.row?.attendee?.pricingOptions || [];\n\n      if (options.length === 0) {\n        return [\n          id: 0,\n          name: \xe2\x80\x98No pricing options\xe2\x80\x99,\n        ];\n      }\n\n      return options;\n    }, \n  },\n  \xe2\x80\xa6\n];\n
Run Code Online (Sandbox Code Playgroud)\n

行数据

\n
const rows = [\n  {\n     id: 1,\n     attendee: {\n       id: 1234,\n       pricingOptions: [\n         {\n           id: 2342342342,\n           name: \xe2\x80\x98Credit Card\xe2\x80\x99,\n           selectedOption: true,\n         },\n         {\n           id: 99994,\n           name: \xe2\x80\x98Cash\xe2\x80\x99,\n           selectedOption: false,\n         },\n       ],\n     }\n  },\n];\n
Run Code Online (Sandbox Code Playgroud)\n

所以我不知道如何告诉数据表如何找到所选的选项。另外,当我点击某个东西时,如何控制它?

\n

0xt*_*xts 1

疑虑

MUI DataGrid 仅将其ReactNode视为有效选项,因此任何选项都接受作为有效选项的字符串并呈现它。您正在尝试使用对象,但这并不意味着您无法实现您想要实现的目标。

对于您的第一期 -

我不确定如何设置选择哪个选项

一个选项是根据field列定义的值来考虑的,并且它将按原样采用该值,如果它是有效的,那么ReactNode您就可以开始了。

至于你的第二个问题——

当我单击一个选项时,我收到一条错误消息,内容为“组件正在将不受控制的输入更改为受控制”。

所有 MUI 组件都会进行参考检查,以确保在受控状态下,输入值相同。在您的情况下,在一种情况下您手动返回数组,而在另一种情况下,您options从行返回。这就是为什么 MUI 说你似乎正在从不受控制的状态进入受控制的状态。

如何实现这一目标?

您需要利用通过GridSingleSelectColDef界面提供的所有不同功能,如下所示 -

import * as React from "react";
import {
  GridRowsProp,
  DataGrid,
  GridColDef,
  GridRowModel
} from "@mui/x-data-grid";
import { randomId } from "@mui/x-data-grid-generator";

const initialRows: GridRowsProp = [
  {
    id: randomId(),
    attendee: {
      id: randomId(),
      pricingOptions: [
        { id: randomId(), name: "Credit Card", selected: false },
        { id: randomId(), name: "Cash", selected: false },
        { id: randomId(), name: "Net Banking", selected: true },
        { id: randomId(), name: "Free", selected: false }
      ]
    }
  },
  {
    id: randomId(),
    attendee: {
      id: randomId(),
      pricingOptions: [
        { id: randomId(), name: "Credit Card", selected: true },
        { id: randomId(), name: "Net Banking", selected: false },
        { id: randomId(), name: "Debit Card", selected: false },
        { id: randomId(), name: "Free", selected: false }
      ]
    }
  },
  {
    id: randomId(),
    attendee: {
      id: randomId(),
      pricingOptions: [
        { id: randomId(), name: "Credit Card", selected: false },
        { id: randomId(), name: "Cash", selected: true },
        { id: randomId(), name: "Net Banking", selected: false },
        { id: randomId(), name: "Debit Card", selected: false }
      ]
    }
  },
  {
    id: randomId(),
    attendee: {
      id: randomId(),
      pricingOptions: [
        { id: randomId(), name: "Credit Card", selected: false },
        { id: randomId(), name: "Cash", selected: false },
        { id: randomId(), name: "Net Banking", selected: false },
        { id: randomId(), name: "Debit Card", selected: true },
        { id: randomId(), name: "Free", selected: false }
      ]
    }
  },
  {
    id: randomId(),
    attendee: {
      id: randomId(),
      pricingOptions: []
    }
  }
];

export default function SingleSelectAsObject() {
  const [rows, setRows] = React.useState(initialRows);

  const processRowUpdate = (newRow: GridRowModel) => {
    const updatedRow = { ...newRow, isNew: false };
    setRows(rows.map((row) => (row.id === newRow.id ? updatedRow : row)));
    return updatedRow;
  };

  const columns: GridColDef[] = [
    { field: "id", headerName: "ID", width: 320, editable: true },
    {
      field: "attendee",
      headerName: "Payment Options",
      width: 220,
      editable: true,
      type: "singleSelect",
      getOptionLabel: (value: any) => {
        return value?.name;
      },
      getOptionValue: (value: any) => value?.name,
      valueGetter: (option) => {
        const value =
          option?.value?.pricingOptions?.find((opt) => !!opt.selected)?.name ||
          "";
        return value;
      },
      valueOptions: (params) => {
        const options: Array<any> =
          rows.find((row) => row?.id === params.row?.id)?.attendee
            ?.pricingOptions || [];
        if (!options?.length) {
          options.push({
            id: randomId(),
            name: "No Pricing Option",
            selected: true
          });
          return options;
        } else {
          return options;
        }
      },
      valueSetter: (params) => {
        const newRow = {
          ...params.row,
          attendee: {
            ...params.row?.attendee,
            pricingOptions: params.row?.attendee?.pricingOptions?.map((opt) => {
              if (opt?.name === params?.value) {
                return { ...opt, selected: true };
              }
              if (opt?.name !== params?.value && !!opt?.selected) {
                return { ...opt, selected: false };
              }
              return opt;
            })
          }
        };
        return newRow;
      }
    }
  ];

  return (
    <DataGrid
      rows={rows}
      columns={columns}
      editMode="row"
      processRowUpdate={processRowUpdate}
    />
  );
}

Run Code Online (Sandbox Code Playgroud)

这是Codesandbox 链接

注意- 我已经使用了processRowUpdateprop,这不是必需的。我只是因为喜欢才使用它。另外,将行保留在useState像我一样的位置,而不是直接使用变量。