useSelect with useForm in antd
On edit page, I have list of roles, containing id as number and name as string, using useSelect with Select. But It shows the ID only and when submit to server, ID goes as string. Anyway to resolve that
14 Replies
Hi @viveksingh0143. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
Yes, you can resolve this issue by using the
useSelect
hook provided by Refine. This hook allows you to manage the <Select>
component when records in a resource need to be used as select options. It also ensures that the defaultValue
is included in the options.
Here is an example from the Refine documentation:
In this example, useSelect
is used to fetch the roles and the defaultValue
is set to the id
of the role that should be selected by default. The selectProps
returned by useSelect
are then spread into the <Select>
component to populate it with options and preselect the default value.
For the issue of ID going as string, you can handle it in the submit function by converting the string ID back to a number before sending it to the server.
Source: Refine Documentation (https://refine.dev/docs/api-reference/antd/hooks/field/useSelect)
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@940119979334967366> kapa.ai is still learning and improving, please let us know how it did by reacting below
yappiest-sapphire•11mo ago
@kapa.ai I am using with combination of Form.Item, and it shows tags with blank values
export interface IRole {
id: number;
name: string;
status: "ACTIVE" | "INACTIVE";
abilities: any[]
}
const { formProps, saveButtonProps, queryResult } = useForm<IUser>();
const usersData = queryResult?.data?.data;
const { selectProps: rolesSelectProps } = useSelect<IRole>({
resource: "roles",
defaultValue: usersData?.roles?.map(r => r.id)
});
<Form.Item
label={translate("users.fields.roles")}
name={["roles"]}
rules={[{ required: true }]}
>
<Select mode="multiple" {...rolesSelectProps} allowClear onSearch={undefined} filterOption={true} optionFilterProp="label" />
</Form.Item>
Let me check the knowledge base for you. One moment! :books:
----------------------
The issue you're facing might be due to the way you're setting the
defaultValue
in the useSelect
hook. The defaultValue
should be the id
of the role that should be selected by default. However, in your case, you're setting it to usersData?.roles?.map(r => r.id)
, which is an array of role IDs. This might be causing the Select component to display tags with blank values.
Here's how you can modify your code:
In this example, the defaultValue
is set to the id
of the first role in the usersData.roles
array. This should preselect the corresponding role in the Select component and display its name instead of a blank tag.
Please note that this is a simplified example and the actual implementation might vary based on your specific use case and the structure of your data.
Source: Refine Documentation (https://refine.dev/docs/api-reference/antd/hooks/field/useSelect)
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@940119979334967366> kapa.ai is still learning and improving, please let us know how it did by reacting below
yappiest-sapphire•11mo ago
@kapa.ai But roles have multiple values and <Select> is referred to multiple mode
Let me check the knowledge base for you. One moment! :books:
----------------------
In the case of multiple selections, you can indeed pass an array of IDs as the
defaultValue
to the useSelect
hook. However, if you're seeing blank values, it might be due to the fact that the labels for these IDs are not fetched yet when the component renders.
Refine's useSelect
hook handles this by sending a request via the useMany
hook to fetch the data and mark them as selected. This ensures that the labels for the default values exist in the current options array.
Here's how you can modify your code:
In this example, the defaultValue
is set to an array of role IDs. The useSelect
hook sends a useMany
query to the backend with these IDs and appends them to the options of the Select
component.
Please note that this is a simplified example and the actual implementation might vary based on your specific use case and the structure of your data.
Source: Refine Documentation (https://refine.dev/docs/api-reference/antd/hooks/field/useSelect)
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@940119979334967366> kapa.ai is still learning and improving, please let us know how it did by reacting below
yappiest-sapphire•11mo ago
@kapa.ai yet blank tags, can't any way, that select match the string with number as ID
Let me check the knowledge base for you. One moment! :books:
----------------------
The issue you're facing might be due to the data type mismatch between the
defaultValue
and the value
of the options in the Select
component. If the defaultValue
is a string and the value
of the options is a number, Ant Design's Select
component might not be able to match them correctly, resulting in blank tags.
To resolve this, you can convert the defaultValue
to a number before passing it to the useSelect
hook. Here's how you can modify your code:
In this example, the defaultValue
is set to an array of role IDs, which are converted to numbers using the Number()
function. This should ensure that the defaultValue
matches the value
of the options in the Select
component.
Please note that this is a simplified example and the actual implementation might vary based on your specific use case and the structure of your data.
Source: Refine Documentation (https://refine.dev/docs/api-reference/antd/hooks/field/useSelect)
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@940119979334967366> kapa.ai is still learning and improving, please let us know how it did by reacting below
yappiest-sapphire•11mo ago
@kapa.ai useSelect auto convert the optionValue to string, can we avoid in any way
@kapa.ai Got the solution, I am mentioning for someone, who have stuck in similar situation:
<Form.Item
label={translate("users.fields.roles")}
name={["roles"]}
rules={[{ required: true }]}
getValueProps={(value: any[]) => {
return {
value: value?.map((item) => String(item?.id)),
};
}}
getValueFromEvent={(selected: string[]) => {
return selected?.map((item) => ({ id: Number(item) }));
}}
>
<Select mode="multiple" {...rolesSelectProps} allowClear onSearch={undefined} filterOption={true} optionFilterProp="label" />
</Form.Item>
<Form.Item
label={translate("users.fields.plant")}
name={["plant", "id"]}
getValueProps={(value: any) => {
return {
value: value ? String(value) : null,
};
}}
getValueFromEvent={(selected: string) => {
return selected ? Number(selected) : null;
}}
>
<Select {...plantSelectProps} allowClear onSearch={undefined} filterOption={true} optionFilterProp="label" />
</Form.Item>
Let me check the knowledge base for you. One moment! :books:
----------------------
I'm glad you found a solution! Your approach of using
getValueProps
and getValueFromEvent
to handle the data type mismatch between the defaultValue
and the value
of the options in the Select
component is indeed a good solution.
Here's your solution for reference:
In this solution, getValueProps
is used to convert the value
to a string before it's passed to the Select
component, and getValueFromEvent
is used to convert the selected value back to a number when it's returned from the Select
component. This ensures that the defaultValue
matches the value
of the options in the Select
component, preventing the issue of blank tags.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@940119979334967366> kapa.ai is still learning and improving, please let us know how it did by reacting below