skip to Main Content

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


  1. 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}

    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search