refine.dev
和 AntDesign
构建仪表板。
我的一个实体具有多对多关系,该关系在 API 中作为具有
id
属性的对象数组返回。
{
"id": 1,
"relations": [
{
"id": 1
},
{
"id": 2
}
]
}
我需要构建一个带有“多选”组件的表单。我遵循本教程。但不幸的是,它仅提供“多对一”关系的示例。
首先我生成
selectProps
。这部分一切顺利。
const { selectProps: relationsSelectProps } = useSelect<Relation>({
resource: 'relations',
optionLabel: 'name',
defaultValue: record?.relations.map((r) => r.id),
});
然后开始问题。当我尝试创建表单项时
<Form.Item
name={['relations']}
>
<Select
mode="multiple"
{...relationsSelectProps}
/>
</Form.Item>
我无法让它与多个嵌套对象一起使用。
我尝试了不同的名称路径:
['relations', 'id']
和['relations', '*', 'id']
尝试使用
normalize
属性。
我真的不想在后端压平这些对象,所以问题是:在项目的 React 端实现这项工作的最佳实践是什么?
因此,您可以通过向
Form.Item
组件添加两个属性来完成此操作。
getValueFromEvent
将 Select 的值转换为 formgetValueProps
反过来做<Form.Item
name={['relations']}
getValueFromEvent={(values) => {
return values.map((id: number) => ({ id }));
}}
getValueProps={(ids) => {
return ids?.map(({ id }: { id: number }) => id);
}}
>
<Select
mode="multiple"
{...selectProps}
/>
</Form.Item>
然后帖子(补丁)请求看起来就是正确的方式:
{
"relations": [
{ "id": 1 },
{ "id": 2 }
],
// other fields
}
所以第一部分是关于如何尝试设置表单项以与您的模型对齐..
Form.Item 上带有 {[something, child-of-somthing]} 的“名称”基本上是点符号
假设我有一个与之有关系的模型,例如
export interface ISubscription {
id: number;
sku: string;
customer: ICustomer
}
ICustomer 看起来像这样
export interface ICustomer {
id: number;
name: string;
surname:: string;
}
当您设置 Form.Item 时,您可以使用 {[]} 获取嵌套值
<Form.Item
label="Customer"
name={["customer", "name"]}
>
<Input />
</Form.Item>
其次,当您超出 Fine.dev 的基本用例时,使用 antd 进行多项选择会更受欢迎。
我不能 100% 确定您的用例,但例如当我必须使用其中的自定义标签进行多重选择时。
<Form.Item label="Custom Tags">
<Select
mode="multiple"
value={customTags}
onSelect={handleSelect}
onDeselect={handleDeselect}
>
{customTagOptions}
</Select>
</Form.Item>
但是您需要制作与此类似的自己的自定义选项
const customTagOptions = useMemo(() => {
return tagDataResult?.data
?.map(
// build an array with the id and label for the select option
(t) => ({ id: t.id, label: `${t.tagType.name} : ${t.name}` })
)
.sort(
// then sort everything
(a, b) =>
a.label.localeCompare(b.label, undefined, { sensitivity: "base" })
)
.map(
// then build the final options
(t) => (
<Option key={t.id} value={t.id} title={t.label}>
{t.label}
</Option>
)
);
}, [tagDataResult?.data]);
因为是的,antD/refine 组合不会让你开箱即用地做你想做的事..你在这里有点与框架作斗争。
希望这对大家有一点帮助