national-gold
national-gold2y ago

Multiple select for nested objects with IDs

Hi everyone. I'm trying to build a Form.Item with a Select inside for multiple related objects. My base objects look like this:
{
"id": 1,
"relations": [
{
"id": 1
},
{
"id": 2
}
]
}
{
"id": 1,
"relations": [
{
"id": 1
},
{
"id": 2
}
]
}
So I want <Form.Item> to set an array of objects, not just numbers. It works just fine for “many-to-one” relation with NamePath (name={['relation', 'id']}), but when it comes to “one-to-many” relation NamePath won't help. I was trying to play with normalize and other things, but with no luck.
7 Replies
generous-apricot
generous-apricot2y ago
Hi @konstantinbodnia, Can you give more detailed information about what you want to do? reporoduced code on github, stackblitz or codesandbox would be awesome 🙏
ambitious-aqua
ambitious-aqua2y ago
Hey @konstantinbodnia, I think i got what you're trying to achieve. 🤔 Let's start with using name="relation" instead of relation.id And we can use getValueFromEvent and getValueProps to get/set the values to the form. getValueFromEvent callback can be used to get the value from the onChange event of the Select component. So you can map the value appropriately to your form state. getValueProps can be used to pass the values to the child element (in your case <Select>) I wonder which data provider you're using? If it's a compatible one with the @pankod/refine-inferencer I think you should give it a try 🚀 Inferencer will try to resolve the data and create a code for your components. You can find a sample solution in its generated code and also it can give you a great head start 🚀
ambitious-aqua
ambitious-aqua2y ago
national-gold
national-gold2y ago
I'm using nestjsx/crud as a data provider these two functions did the trick
ambitious-aqua
ambitious-aqua2y ago
Great!
national-gold
national-gold2y ago
getValueFromEvent={(values) => {
return values.map((id: number) => ({ id }));
}}
getValueProps={(ids) => {
return ids?.map(({ id }: { id: number }) => id);
}}
getValueFromEvent={(values) => {
return values.map((id: number) => ({ id }));
}}
getValueProps={(ids) => {
return ids?.map(({ id }: { id: number }) => id);
}}
But for some reason it is now very slow... Ok, thank you for your help, @aliemirs . This works.
const { selectProps: relationsSelectProps } = useSelect<Relation>({
resource: 'relations',
defaultValue: relationsIds,
});

<Form.Item
name={['relations']}
getValueFromEvent={(values) => values.map((id: number) => ({ id }))}
getValueProps={(ids) => ids?.map(({ id }: { id: number }) => id)}
>
<Select
mode="multiple"
{...relationsSelectProps}
/>
</Form.Item>
const { selectProps: relationsSelectProps } = useSelect<Relation>({
resource: 'relations',
defaultValue: relationsIds,
});

<Form.Item
name={['relations']}
getValueFromEvent={(values) => values.map((id: number) => ({ id }))}
getValueProps={(ids) => ids?.map(({ id }: { id: number }) => id)}
>
<Select
mode="multiple"
{...relationsSelectProps}
/>
</Form.Item>
But now I have one more following issue. The values won't get pre-selected in the edit form.
ambitious-aqua
ambitious-aqua2y ago
@konstantinbodnia can you check the relationSelectProps to see if its props are matching your getValueProps ? This might be the issue for the default values