I have a multi-step form that has a "next" button that pushes you through the different steps. on the last page it changes to a "submit" button that connects to a form.
I dynamically set the type
and form
attributes on the button, which should theoretically trigger the forms onSubmit action. But clicking "submit" does not trigger the onSubmit
function.
Is it possible to have a button outside of a <form>
tag submit a form dynamically like this?
The specific button is:
<button
className="btn text-white btn-neutral w-24"
onClick={
step < 3
? () => {
handleNext();
}
: undefined
}
type={step >= 3 ? "submit" : undefined}
form={step >= 3 ? "visa-form" : undefined}
>
{step >= 3 ? "Submit" : "Next"}
</button>
The entire files code is below:
"use client";
import ...;
export default function IntakeForm() {
const [step, setStep] = useState(0);
const {
register,
unregister,
handleSubmit,
formState: { errors },
trigger,
watch,
} = useForm<VisaRecommendationFormModel>({
resolver: zodResolver(VisaRecommendationFormSchema),
});
const onSubmit = (data: VisaRecommendationFormModel) => {
console.log("Form submitted with data:", data);
// Add your form submission logic here
};
const handlePrevious = () => {
setStep(step - 1);
};
const handleNext = async () => {
console.log("handling next");
const isValid = await trigger(["fields", "to", "validate"]);
if (isValid) {
const nextStep = step + 1;
setStep(nextStep);
}
};
return (
<div className="relative flex flex-col justify-center items-center pt-14 gap-10">
<form
className="border-2 rounded-xl p-14 h-[448px] w-[660px] flex flex-col items-center justify-center"
onSubmit={handleSubmit(onSubmit)}
id="visa-form"
>
{step === 0 && <CurrentLocationInput register={register} />}
{step === 1 && <FamilyInformationInput register={register}/>}
{step === 2 && <CareerInformationInput register={register} />}
{step === 3 && <PersonalInformationInput register={register} />}
</form>
<div className="flex flex-row gap-x-96">
<button
className={`btn text-white btn-neutral w-24 ${
step <= 0 ? "btn-disabled opacity-0" : "btn-active opacity-100"
}`}
onClick={() => {
handlePrevious();
}}
>
Previous
</button>
<button
className="btn text-white btn-neutral w-24"
onClick={
step < 3
? () => {
handleNext();
}
: undefined
}
type={step >= 3 ? "submit" : undefined}
form={step >= 3 ? "visa-form" : undefined}
>
{step >= 3 ? "Submit" : "Next"}
</button>
</div>
</div>
);
}
2
Answers
you can have two buttons, on the last stage submit button should be rendered, and on the steps, the next button, for example
{step < 3 && next</button}
{step === 3 && next</button}
I copied over to a sandbox, and after stripping out the unreferenced items, I’m not able to reproduce your problem. I am seeing it’s increasing faster than you might be anticipating, but the submit method is firing for me.
Here’s a link to the sandbox.