How to do conditional rendering in forms with Antd?

I'm trying to make a field that is only displayed according to the state of another form field, however, using form.getFieldValue I'm not having success, the values ​​that come from the API are not recognized as soon as the api loads, however, using onValuesChange behavior is correct after loading the api, but the initial values ​​are not recognized to show the field, how to fix this problem? https://gist.github.com/torugok/edf059216f5aec208897bb6a1ca38f23
Gist
Code error antd
Code error antd. GitHub Gist: instantly share code, notes, and snippets.
20 Replies
kapa.ai
kapa.ai5mo ago
Hi @Toguro. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- You can use the watch function from the useForm hook to monitor changes in the form field values. This function returns the current value of the specified field and re-renders the component whenever the field value changes. You can use this to conditionally render form fields based on the value of another field. Here is an example from the knowledge sources:
const {
handleSubmit,
watch,
formState: { errors },
} = useForm<IFormValue, HttpError, IFormValue>({
mode: "onChange",
defaultValues,
resolver: yupResolver(schema),
});

const work = watch("work");

return (
<form
style={{ display: "flex", flexDirection: "column" }}
onSubmit={handleSubmit(handleSubmission)}
>
{/* other form fields */}
{work === "employed" && (
<>
<Controller
control={control}
name="company"
render={({ field }) => (
<TextField
{...field}
fullWidth
sx={{ maxWidth: 600 }}
label="Company"
margin="dense"
/>
)}
/>
</>
)}
</form>
);
const {
handleSubmit,
watch,
formState: { errors },
} = useForm<IFormValue, HttpError, IFormValue>({
mode: "onChange",
defaultValues,
resolver: yupResolver(schema),
});

const work = watch("work");

return (
<form
style={{ display: "flex", flexDirection: "column" }}
onSubmit={handleSubmit(handleSubmission)}
>
{/* other form fields */}
{work === "employed" && (
<>
<Controller
control={control}
name="company"
render={({ field }) => (
<TextField
{...field}
fullWidth
sx={{ maxWidth: 600 }}
label="Company"
margin="dense"
/>
)}
/>
</>
)}
</form>
);
In this example, the work field is being watched. If its value is "employed", the company field is rendered. Otherwise, it is not. For your case, you can replace "work" with the name of the field you want to watch, and "employed" with the value that should trigger the conditional rendering. If you're using Ant Design, you can replace the TextField component with the appropriate Ant Design form field component. For more information on conditional rendering in React, you can check out this guide (https://refine.dev/blog/react-conditional-rendering#introduction). For more information on form handling in Refine with Ant Design, you can check out this documentation (https://refine.dev/docs/ui-integrations/ant-design/hooks/use-drawer-form#how-can-i-change-the-form-data-before-submitting-it-to-the-api). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5mo ago
<@266951832377491457> kapa.ai is still learning and improving, please let us know how it did by reacting below
fascinating-indigo
fascinating-indigo5mo ago
not work in Ant Design... @kapa.ai
kapa.ai
kapa.ai5mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- I'm sorry, but your question is not clear. Could you please provide more details about the issue you're facing with Ant Design in Refine? Are you having trouble with a specific component, or is it a general issue? The more details you provide, the better I can assist you. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5mo ago
<@266951832377491457> kapa.ai is still learning and improving, please let us know how it did by reacting below
fascinating-indigo
fascinating-indigo5mo ago
{form.getFieldValue("type") == "TypeTarget" ? ( <Form.Item label={"Conditional Field"} name={["conditionalField"]} rules={[ { required: isTypeTarget(), }, ]} > <Input /> </Form.Item> ) : ( <></> )} @kapa.ai
kapa.ai
kapa.ai5mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- In Ant Design with Refine, you can use the useForm hook to get the form instance and then use the getFieldValue method to get the value of a specific field. You can then use this value to conditionally render form fields. Here is an example:
import { useForm } from "@refinedev/antd";
import { Form, Input } from "antd";

export const MyForm = () => {
const { formProps } = useForm();

return (
<Form {...formProps} layout="vertical">
<Form.Item
label="Type"
name="type"
>
<Input />
</Form.Item>
{formProps.form.getFieldValue("type") === "TypeTarget" && (
<Form.Item
label={"Conditional Field"}
name={["conditionalField"]}
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
)}
</Form>
);
};
import { useForm } from "@refinedev/antd";
import { Form, Input } from "antd";

export const MyForm = () => {
const { formProps } = useForm();

return (
<Form {...formProps} layout="vertical">
<Form.Item
label="Type"
name="type"
>
<Input />
</Form.Item>
{formProps.form.getFieldValue("type") === "TypeTarget" && (
<Form.Item
label={"Conditional Field"}
name={["conditionalField"]}
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
)}
</Form>
);
};
In this example, the Conditional Field is only rendered if the value of the type field is "TypeTarget". Please note that this example assumes that you have a field named type in your form. Replace "type" and "TypeTarget" with the actual name and value of your field. For more information on form handling in Refine with Ant Design, you can check out this documentation (https://refine.dev/docs/ui-integrations/ant-design/hooks/use-form). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5mo ago
<@266951832377491457> kapa.ai is still learning and improving, please let us know how it did by reacting below
fascinating-indigo
fascinating-indigo5mo ago
this code you sended not work for initial values from api @kapa.ai
kapa.ai
kapa.ai5mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- I see, you're having trouble with the initial values from the API not being recognized for conditional rendering. This is likely because the form fields are rendered before the API response is received, so the initial values are not yet available when the conditional rendering is evaluated. One way to handle this is to use the formLoading return value from the useForm hook. This value is true when the form is being submitted or data is being fetched for the "edit" or "clone" mode. You can use this to delay the rendering of your form until the initial values are available. Here's an example:
import { useForm } from "@refinedev/antd";
import { Form, Input, Spin } from "antd";

export const MyForm = () => {
const { formProps, formLoading } = useForm();

if (formLoading) {
return <Spin />;
}

return (
<Form {...formProps} layout="vertical">
<Form.Item
label="Type"
name="type"
>
<Input />
</Form.Item>
{formProps.form.getFieldValue("type") === "TypeTarget" && (
<Form.Item
label={"Conditional Field"}
name={["conditionalField"]}
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
)}
</Form>
);
};
import { useForm } from "@refinedev/antd";
import { Form, Input, Spin } from "antd";

export const MyForm = () => {
const { formProps, formLoading } = useForm();

if (formLoading) {
return <Spin />;
}

return (
<Form {...formProps} layout="vertical">
<Form.Item
label="Type"
name="type"
>
<Input />
</Form.Item>
{formProps.form.getFieldValue("type") === "TypeTarget" && (
<Form.Item
label={"Conditional Field"}
name={["conditionalField"]}
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
)}
</Form>
);
};
In this example, a loading spinner is displayed while the form data is being fetched. Once the data is available, the form is rendered with the initial values, and the conditional rendering should work as expected. For more information on form handling in Refine with Ant Design, you can check out this documentation (https://refine.dev/docs/ui-integrations/ant-design/hooks/use-form). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5mo ago
<@266951832377491457> kapa.ai is still learning and improving, please let us know how it did by reacting below
fascinating-indigo
fascinating-indigo5mo ago
not work @kapa.ai , the field not is showing in initial screen after the api load the data
kapa.ai
kapa.ai5mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- I'm sorry for the confusion earlier. The issue you're facing is due to the fact that the form fields are rendered before the API response is received. Therefore, the initial values are not yet available when the conditional rendering is evaluated. Unfortunately, the knowledge sources provided do not contain a direct solution to this issue. However, a common approach to handle this in React is to use a state variable to store the API response and update this state when the response is received. You can then use this state for conditional rendering. Here's a general example:
import { useState, useEffect } from 'react';
import { Form, Input } from 'antd';

export const MyForm = () => {
const [type, setType] = useState(null);
const { formProps } = useForm();

useEffect(() => {
// Fetch initial values from API
fetch('/api/endpoint')
.then(response => response.json())
.then(data => setType(data.type));
}, []);

return (
<Form {...formProps} layout="vertical">
<Form.Item label="Type" name="type">
<Input />
</Form.Item>
{type === 'TypeTarget' && (
<Form.Item
label="Conditional Field"
name="conditionalField"
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
)}
</Form>
);
};
import { useState, useEffect } from 'react';
import { Form, Input } from 'antd';

export const MyForm = () => {
const [type, setType] = useState(null);
const { formProps } = useForm();

useEffect(() => {
// Fetch initial values from API
fetch('/api/endpoint')
.then(response => response.json())
.then(data => setType(data.type));
}, []);

return (
<Form {...formProps} layout="vertical">
<Form.Item label="Type" name="type">
<Input />
</Form.Item>
{type === 'TypeTarget' && (
<Form.Item
label="Conditional Field"
name="conditionalField"
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
)}
</Form>
);
};
In this example, the type state is updated with the value fetched from the API, and this state is used for conditional rendering. Please replace '/api/endpoint' with your actual API endpoint and adjust the data processing as needed. Please note that this is a general example and might need adjustments based on your actual API and data structure. For more information on form handling in Refine with Ant Design, you can check out this documentation (https://refine.dev/docs/ui-integrations/ant-design/hooks/use-form). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5mo ago
<@266951832377491457> kapa.ai is still learning and improving, please let us know how it did by reacting below
fascinating-indigo
fascinating-indigo5mo ago
Form.useWatch solved my problem @kapa.ai