疑问
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}
/>
);
}
这是一个
Codesandbox链接。
注意 - 我使用了
processRowUpdate
属性,这并非必需。我只是喜欢使用它。另外,保持行在
useState
中,像我这样使用状态变量,而不是直接使用变量。
payment
字段设置为有效值吗(即使它是默认值或空值)从一开始就设置好了吗? - VonCpricingOptions1st
中有一个名为selectedOption
的属性,如果该属性为true,则表示该选项被选中。 - jrock2004field: 'attendee.pricingOptions'
,它会期望attendee.pricingOptions
的值是被选中的值。然而,attendee.pricingOptions
是一个数组。你可以为DataGrid扁平化你的行数据结构,在每一行添加一个payment
字段,该字段将是所选定的定价选项的id
。然后将字段设置为payment
。当用户进行更改时,您需要处理此编辑并更新原始数据结构(onEditCellChangeCommit
)。 - VonC