I’m currently working on a React project which is using Shadcn ui Form and React Form Hook to create the forms. I have a MainForm component responsible for rendering either an ArrivalForm or DepartureForm based on user selection.
How can I retrieve the values entered in both the MainForm and ArrivalForm components specifically when the user selects Arrival and submits the MainForm?
Here’s a simplified version of my code structure:
//this is mainform.tsx
export function MainForm() {
const { toast } = useToast();
const [formSelected, setFormSelected] = useState<string | null>('');
// 1. Define your form using Schema define from z.
const form = useForm<z.infer<typeof mainFormSchema>>({
resolver: zodResolver(mainFormSchema),
defaultValues: {
fullname: '',
email: '',
formSelected: undefined,
},
});
// 2. Define a submit handler.
function onSubmit(values: z.infer<typeof mainFormSchema>) {
console.log(values);
toast({
title: 'Submit Values is:',
description: (
<pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
<code className="text-white">{JSON.stringify(values, null, 2)}</code>
</pre>
),
});
}
// 3. Return a form
return (
<>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField
control={form.control}
name="fullname"
render={({ field }) => (
<FormItem>
<FormLabel>Fullname</FormLabel>
<FormControl>
<Input placeholder="Please input your full name" {...field} />
</FormControl>
<FormDescription>
This is your public display name.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input placeholder="Please input your email" {...field} />
</FormControl>
<FormDescription>
This is your public display name.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="formSelected"
render={({ field }) => (
<FormItem>
<RadioGroup
onValueChange={field.onChange}
defaultValue={field.value}
>
<div className="flex">
<div className="flex items-center space-x-2 px-2">
<RadioGroupItem
value="arrival"
id="arrival"
onClick={() => {
setFormSelected('arrival');
}}
/>
<Label htmlFor="arrivalRadio">Arrival</Label>
</div>
<div className="flex items-center space-x-2 px-2">
<RadioGroupItem
value="departure"
id="departure"
onClick={() => {
setFormSelected('departure');
}}
/>
<Label htmlFor="departureRadio">Departure</Label>
</div>
</div>
</RadioGroup>
<FormMessage />
</FormItem>
)}
/>
{formSelected === 'arrival' ? <ArrivalForm /> : null}
{formSelected === 'departure' ? <DepartureForm /> : null}
<Button type="submit">Submit</Button>
</form>
</Form>
</>
);
}
// This is arrivalForm.tsx
export function ArrivalForm() {
// 1. Define your form using Schema define from z.
const form = useForm<z.infer<typeof arrivalFormSchema>>({
resolver: zodResolver(arrivalFormSchema),
defaultValues: {
guestName: '',
arrivalInfo: '',
},
});
// 2. Define a submit handler.
function arrivalFormSubmit(values: z.infer<typeof arrivalFormSchema>) {
// pass form values to the parent form:
console.log(values);
}
// 3. Return a form
return (
<Form {...form}>
<form
onSubmit={form.handleSubmit(arrivalFormSubmit)}
className="space-y-8"
>
<FormField
control={form.control}
name="guestName"
render={({ field }) => (
<FormItem>
<FormLabel>Guest Name</FormLabel>
<FormControl>
<Input placeholder="input Guest Name" {...field} />
</FormControl>
<FormDescription>Guest Name here</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="arrivalInfo"
render={({ field }) => (
<FormItem>
<FormLabel>Arrival Infomation</FormLabel>
<FormControl>
<Input placeholder="input Arrival Info Here" {...field} />
</FormControl>
<FormDescription>Arrival Info here</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</form>
</Form>
);
}
// mainFormSchema
export const mainFormSchema = z.object({
fullname: z.string().min(2, {
message: 'Username must be at least 2 characters.',
}),
email: z.string().min(2, {
message: 'Username must be at least 2 characters.',
}),
formSelected: z.enum(['arrival', 'departure'], {
message: 'You need to select a booking type.',
}),
});
// arrivalFormSchema
export const arrivalFormSchema = z.object({
guestName: z.string().min(2, {
message: 'Guest name must be at least 2 characters.',
}),
arrivalInfo: z.string().min(2, {
message: 'Please enter arrival info',
}),
});