ui
ui copied to clipboard
Form in dialog doesn't send the Request.
Hello, i have a little Problem.
so thats my Code:
<Dialog open={open} onOpenChange={setOpen}>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)}>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogDescription>
Make changes to your profile here. Click save when youre done.
</DialogDescription>
</DialogHeader>
<FormField
control={form.control}
name="full_name"
render={({ field }) => (
<FormItem>
<FormLabel>Name</FormLabel>
<FormControl>
<Input placeholder="Name" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<DialogFooter>
<Button type="submit">Submit</Button>
</DialogFooter>
</DialogContent>
</form>
</Form>
</Dialog>
That looks like
The Problem now is, that the Form doesnt send the Request. It should be, or am i wrong ?
When i move the <Form>
into the <DialogContent>
the Form works but the styles are wrong
I have a similar setup, but I've separated the Form into its own component and nested it into the Dialog as shown below:
"use client"
/* a bunch of imports you don't care about */
export function TableDialogCustom() {
return (
<Dialog>
<DialogTrigger asChild>
<Button variant="outline">Add Table</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>Add a Table</DialogTitle>
<DialogDescription>
Add a table name and a read-only API key from AirTable
</DialogDescription>
</DialogHeader>
<div className="grid gap-4 py-4">
<div className="grid items-center gap-4">
<TableForm />
</div>
</div>
</DialogContent>
</Dialog>
)
}
"use client"
/* a bunch of imports you don't care about */
export function TableForm() {
/* a bunch of resolver/onclick stuff you don't care about */
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField
control={form.control}
name="table_name"
render={({ field }) => (
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input placeholder="Table Name" {...field} />
</FormControl>
<FormDescription>
Enter your table name here.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="api_key"
render={({ field }) => (
<FormItem>
<FormLabel>API Key</FormLabel>
<FormControl>
<Input placeholder="API Key" {...field} />
</FormControl>
<FormDescription>
Enter your API Key here.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Submit</Button>
</form>
</Form>
)
}
It ends up looking like this:
still not working 😢
@daddotmn use button onClick and dispatch submit event with bubbles true
<Form {...form}>
<form ref={formRef} onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
...
</form>
</Form>
...
<Button
onClick={() => {
if (formRef.current) {
formRef.current.dispatchEvent(new Event('submit', { bubbles: true }));
}
}}
>
Continue
</Button>
@daddotmn use button onClick and dispatch submit event with bubbles true
<Form {...form}> <form ref={formRef} onSubmit={form.handleSubmit(onSubmit)} className="space-y-8"> ... </form> </Form> ... <Button onClick={() => { if (formRef.current) { formRef.current.dispatchEvent(new Event('submit', { bubbles: true })); } }} > Continue </Button>
This works fine... but this should work without this workaround.
If you are rendering the form outside the Dialog.Content
, what is happening is that the button is being portaled to the body and as it is not inside the form element the submit will not work. What you can do is:
- Move the form into
Dialog.Content
- Use the form attribute on the submit button
what to do if in case we have a long form containing various fields.. in my case the dialog just scatter height wise due to large no. of fields. i somehow want to adjust the dialog on the screen and scroll the form fields. note: scrollarea isn't working at all in this case.
@daddotmn use button onClick and dispatch submit event with bubbles true
<Form {...form}> <form ref={formRef} onSubmit={form.handleSubmit(onSubmit)} className="space-y-8"> ... </form> </Form> ... <Button onClick={() => { if (formRef.current) { formRef.current.dispatchEvent(new Event('submit', { bubbles: true })); } }} > Continue </Button>
even this doesn't work for me. anybody has a solution for this?
I found this: https://github.com/react-hook-form/react-hook-form/issues/566#issuecomment-612328736
There seem to be several solutions.
- If you have access to
handleSubmit()
function in the component which includes your submit button: invoke it directlyhandleSubmit(onSubmit)()
. - You can set an id on your
<form id="my-form" >
, and add this id to theform
attribute of your submit button:<button type="submit" form="my-form" />
.
Option 1 seems easiest and solved my problem. Option 2 triggered a full page refresh/rerender so i didn't use it.
To resolve this I moved the <Form {...form}/>
component to wrap the entire <Dialog>
component and placed the submit button inside the <DialogContent>
.
Here's the code:
const formSchema = z.object({
is_business: z.boolean().default(false),
// more schema here...
});
export default function NewCxDialog({ open, onOpenChange }) {
const { handleSubmit, control, ...form } = useForm({
resolver: zodResolver(formSchema),
defaultValues: {
is_business: false,
// default values here...
},
});
function onSubmit(e) {
function closeDialog() {
onOpenChange(false);
}
const submitData = async (e) => {
try {
const response = await fetch("/api/new/cx", {
method: "POST",
cache: "no-store",
body: JSON.stringify(e),
headers: {
"Content-Type": "application/json",
},
});
} catch (error) {
throw error;
}
};
// I use sonner for toasts
toast.promise(submitData(), {
loading: "Cargando...",
success: () => {
router.refresh();
closeDialog();
return "Cliente Creado Exitosamente";
},
error: (e) => {
console.error(e);
return "Hubo un error. Intenta nuevamente.";
},
});
}
return (
<Form {...form}>
<Dialog
open={open}
onOpenChange={() => {
form.reset();
onOpenChange();
}}
>
<DialogContent className="max-w-2xl">
<form onSubmit={handleSubmit(onSubmit)}>
<DialogHeader>
<DialogTitle className="!text-primary">
Crear Nuevo Cliente
</DialogTitle>
<DialogDescription>
Llena el formulario con la información de tu cliente.
</DialogDescription>
</DialogHeader>
<div className="grid gap-6 py-4">
<div className="grid grid-cols-2 gap-6">
<FormField
control={control}
name="first_name"
render={({ field }) => (
<FormItem>
<FormLabel>Nombre</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={control}
name="last_name"
render={({ field }) => (
<FormItem>
<FormLabel>Apellido</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
// more code here...
</div>
</div>
<DialogFooter>
<Button type="submit">Crear Cliente</Button>
</DialogFooter>
</form>
</DialogContent>
</Dialog>
</Form>
);
}
If you are rendering the form outside the
Dialog.Content
, what is happening is that the button is being portaled to the body and as it is not inside the form element the submit will not work. What you can do is:
- Move the form into
Dialog.Content
- Use the form attribute on the submit button
Cleanest explanation. Works as expected now. Ty @joaom00
If you are rendering the form outside the
Dialog.Content
, what is happening is that the button is being portaled to the body and as it is not inside the form element the submit will not work. What you can do is:
- Move the form into
Dialog.Content
- Use the form attribute on the submit button
Cleanest explanation. Works as expected now. Ty @joaom00
It's not working
To resolve this I moved the
<Form {...form}/>
component to wrap the entire<Dialog>
component and placed the submit button inside the<DialogContent>
.Here's the code:
const formSchema = z.object({ is_business: z.boolean().default(false), // more schema here... }); export default function NewCxDialog({ open, onOpenChange }) { const { handleSubmit, control, ...form } = useForm({ resolver: zodResolver(formSchema), defaultValues: { is_business: false, // default values here... }, }); function onSubmit(e) { function closeDialog() { onOpenChange(false); } const submitData = async (e) => { try { const response = await fetch("/api/new/cx", { method: "POST", cache: "no-store", body: JSON.stringify(e), headers: { "Content-Type": "application/json", }, }); } catch (error) { throw error; } }; // I use sonner for toasts toast.promise(submitData(), { loading: "Cargando...", success: () => { router.refresh(); closeDialog(); return "Cliente Creado Exitosamente"; }, error: (e) => { console.error(e); return "Hubo un error. Intenta nuevamente."; }, }); } return ( <Form {...form}> <Dialog open={open} onOpenChange={() => { form.reset(); onOpenChange(); }} > <DialogContent className="max-w-2xl"> <form onSubmit={handleSubmit(onSubmit)}> <DialogHeader> <DialogTitle className="!text-primary"> Crear Nuevo Cliente </DialogTitle> <DialogDescription> Llena el formulario con la información de tu cliente. </DialogDescription> </DialogHeader> <div className="grid gap-6 py-4"> <div className="grid grid-cols-2 gap-6"> <FormField control={control} name="first_name" render={({ field }) => ( <FormItem> <FormLabel>Nombre</FormLabel> <FormControl> <Input {...field} /> </FormControl> <FormMessage /> </FormItem> )} /> <FormField control={control} name="last_name" render={({ field }) => ( <FormItem> <FormLabel>Apellido</FormLabel> <FormControl> <Input {...field} /> </FormControl> <FormMessage /> </FormItem> )} /> // more code here... </div> </div> <DialogFooter> <Button type="submit">Crear Cliente</Button> </DialogFooter> </form> </DialogContent> </Dialog> </Form> ); }
Doesn't this render an empty form in place until the Dialog renders a Portal?
IF YOU ARE USING ANY KIND OF FORM RESOLVER: Apart from this above solutions on form there might be issue in your zod schema.If you forgot to add an required zod field schema in the form then there would'nt be any error in form but internally zod stop you from submitting the form.
IF YOU ARE USING ANY KIND OF FORM RESOLVER: Apart from this above solutions on form there might be issue in your zod schema.If you forgot to add an required field zod schema in the form then there would'nt be any error in form but internally zod stop you from submitting the form.
This solution works for me. Thank you @Yogesh070
2. form="my-form"
Thank you! Solved it, there is no need to wrap around Dialog box. There was a problem with zod resolvers in my case and that fixed the problem.
@kgaurav152 did ya manage to solve that issue?
@kgaurav152 did ya manage to solve that issue?
Yes it's working for me. What I did is that I separately made the form and then imported that into the dialog component and it's working since then, have been using this same approach wherever needed and it's working.
Const UpdateProfileForm
Const UpdateProfile
<UpdateProfileForm/>
Worked for me too. i was not having an input component for a schema field and that's why it was invalid every time i submitted the form but i wasn't getting any error as i didn't have registered that schema field with any input component. after making that schema field optional, i got it working.
Thanks everyone.
I faced the same issue myself, what I did is I wrapped the <Dialog> with my <Form> component and separated my
I encountered the same issue. moved from using <form />
to use useForm handle submit function on the button and it worked
return (
<Dialog>
<DialogTrigger asChild>
<button className="w-full text-start">Edit</button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Edit tag</DialogTitle>
<DialogDescription>Edit tag information</DialogDescription>
<Label htmlFor="name">Name</Label>
<Input
placeholder="Birthday"
id="name"
type="text"
{...register("name", {
required: { message: "Tag name is required", value: true },
maxLength: {
value: 30,
message: "Tag Name cannot be grater than 30",
},
})}
/>
</DialogHeader>
<DialogFooter>
<Button
type="button"
onClick={handleSubmit(handleEditTag)}
>
Update
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
Same issue with form not firing submit event when inside a Dialog: Changed from this :
<form onSubmit={submitData}> ---> from here
<Dialog>
<DialogTrigger asChild>
<Button variant="outline">Add New Item</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[500px] w-[700px] ">
....
To this :
<Dialog>
<DialogTrigger asChild>
<Button variant="outline">Add New Item</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[500px] w-[700px] ">
<form onSubmit={submitData}> ----> to here
....
Please follow the method below to solve the problem.
<Dialog onOpenChange={setOpen} open={open}>
<DialogContent>
<DialogHeader>
<DialogTitle>
Are you absolutely sure to reject the request?
</DialogTitle>
<DialogDescription>
This action cannot be undone. This will permanently delete
your account and remove your data from our servers.
</DialogDescription>
</DialogHeader>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-12">
<fieldset >
<FormField
control={form.control}
name="rejectComment"
render={({ field }) => {
return (
<FormItem>
<FormLabel>Reject comment</FormLabel>
<FormControl>
<Input placeholder="Reject comment" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)
}}
/>
<DialogFooter>
<Button className="my-2" type="submit">Save changes</Button>
</DialogFooter>
</fieldset>
</form>
</Form>
</DialogContent>
</Dialog>
This issue has been automatically closed because it received no activity for a while. If you think it was closed by accident, please leave a comment. Thank you.