Ant 设计嵌套对象的多选

问题描述 投票:0回答:2

我正在使用

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 端实现这项工作的最佳实践是什么?

reactjs many-to-many antd react-refine
2个回答
1
投票

因此,您可以通过向

Form.Item
组件添加两个属性来完成此操作。

  1. getValueFromEvent
    将 Select 的值转换为 form
  2. getValueProps
    反过来做
<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
}

0
投票

所以第一部分是关于如何尝试设置表单项以与您的模型对齐..

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 组合不会让你开箱即用地做你想做的事..你在这里有点与框架作斗争。

希望这对大家有一点帮助

© www.soinside.com 2019 - 2024. All rights reserved.