Я создаю дашборд с помощью 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
.
Я действительно не хочу сглаживать эти объекты на стороне бэкэнда, поэтому возникает вопрос: как лучше всего заставить это работать на стороне реагирования проекта?
Да. Но это отношение «один ко многим» назначит массив только идентификаторов. Но мне нужно, чтобы он работал с массивом объектов [{"id": 1}, {"id": 2}]
и т. д.
Итак, первая часть о том, как вы пытаетесь настроить элемент формы в соответствии с вашей моделью.
«Имя» с {[что-то, потомок чего-то]} в Form.Item в основном представляет собой точечную нотацию.
скажем, у меня есть модель, в которой есть отношение, например
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>
Во-вторых, делать множественный выбор с помощью antd намного сложнее, когда вы выходите за рамки базового варианта использования в Refine.dev.
Я не уверен на 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 не позволит вам делать то, что вы хотите из коробки ... вы немного боретесь с фреймворком здесь.
Надеюсь, это немного поможет человеку
Таким образом, вы можете сделать это, добавив два свойства к компоненту Form.Item
.
getValueFromEvent
для преобразования значений Select в форму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
}
Я не совсем понимаю, чего вы пытаетесь достичь. Можете ли вы привести пример? Обычно Select-Item с
mode = "multiple"
всегда дает вам отношениеone-to-many
.