29

im using react-hook-form for form validation and submission ,everything work's fine with single submit type button, now i need to have three buttons , "Save Draft" ,"Preview Data Values in Page" ,and "Submit for approval " ,i can opt-out for a Mode Selection radio Buttons ,But wanted to have three button submit function, which needs form data . adding onchnage for input fields will work ,but form validation needs to write again .

  const { register, handleSubmit } = useForm();
  const onSubmit = (data) => alert(JSON.stringify(data));
  function NeedTohaveFormDataHere1(Data) {

   } function NeedTohaveFormDataHere2(Data) {

   }
    return (  <form onSubmit={handleSubmit(onSubmit)}>
     <Headers />

  <input name="firstName" ref={register} placeholder="First name" />

  <input name="lastName" ref={register} placeholder="Last name" />

  <select name="category" ref={register}>
    <option value="">Select...</option>
    <option value="A">Category A</option>
    <option value="B">Category B</option>
  </select>
  <button onClick={NeedTohaveFormDataHere1}>
   Save Draft
  </button > 
  <button onClick={NeedTohaveFormDataHere2}>
    Preview
  </button>  
  <input type="submit" />
</form>
 );
 }
 

onSubmit function will get form data ,how to get form data in other two button functions ?

sloved .. with

  <button onClick={handleSubmit(NeedTohaveFormDataHere1)}>
   Save Draft
  </button > 
  <button onClick={handleSubmit(NeedTohaveFormDataHere2)}>
    Preview
  </button> 
3
  • 2
    This question is too weak in terms of explanation. Please give proper code and explanation Commented Feb 12, 2021 at 17:55
  • added example code Commented Feb 12, 2021 at 18:45
  • @KiranKumar Still really weak. Would you mind showing more detail? Did you remove the onSubmit from the form also? This doesn't provide enough to help. Commented Aug 16, 2022 at 18:48

10 Answers 10

23

I had the same problem and I resolved it the following way:

I have two buttons. The first button validates and submits the form normally. The second button only validates and calls a custom function.

I'm assuming you have the situation. One button is to save and the other one is to store a draft.

<form id="example-form" onSubmit={handleSubmit(handleOnSave)}>
  <IconButtonTooltip
    form="example-form"
    title="Only save"
  >
    <SaveIcon className={classes.icon} />
  </IconButtonTooltip>

  <IconButtonTooltip
    form="example-form"
    title="Save and sign"
    onClick={handleSubmit(handleOnSingAndSave)}
  >
    <SignatureIcon className={classes.icon} />
  </IconButtonTooltip>
</form>

const handleOnSingAndSave  = () => {
  // Handle things...
}

It works for me!

Sign up to request clarification or add additional context in comments.

Comments

17

if you have to handle the multiple submit buttons in react-hook-form

1. remove your submit method from the form tag and add it to your button click

2. move your submit buttons outside the form tag

const { handleSubmit } = useForm();

<form>
 <input />
 <input />
</form>

<button onClick={handleSubmit((d) => console.log(d))} > Save </button>
<button onClick={handleSubmit((d) => console.log(d))} > Draft </button>

3 Comments

You call the same method with 2 different buttons.
I like this solution because it can actually move the submit buttons out of the form and put them anywhere I need.
This works as intended. I do however experience issues with lists not updating info until page is rendered again. Submit aka. save works and updates my list, but Add to List is not firing of the render, but post data to state.
13

You can use handleSubmit in multiple place.

const handleSubmitDraft=()=>{
  handleSubmit(aync(data)=>{...})()

}
const handleSubmitPreview=()=>{
  handleSubmit((data)=>{...})()
}


<button onClick={handleSubmitDraft}>
   Save Draft
</button > 
<button onClick={handleSubmitPreview}>
    Preview
</button> 

Comments

12

Add a name attribute to your button. Then:

JavaScript

  async function onSubmit(values, e) {

    const submitter = e?.nativeEvent?.submitter;
    console.log(submitter?.name);

TypeScript

  async function onSubmit(
    values: z.infer<typeof formSchema>,
    e: React.FormEvent<HTMLFormElement>,
  ) {
    if (!(e.nativeEvent instanceof SubmitEvent)) return;
    const submitter = e?.nativeEvent?.submitter as HTMLButtonElement;
    if (!(submitter instanceof HTMLInputElement)) return;
    console.log(submitter?.name);

CanIuse SubmitEvent is safe: https://caniuse.com/?search=SubmitEvent

1 Comment

This is the answer. Upvote!
2

You Can add name or id to your button and check the button type as in modern browsers button type is submit by default

<button  name="submit">Submit</button> 
    
    <button  name="draft">Draft</button> 

    <form onSubmit={handleSubmit} > ...

function handleSubmit(event) {
            event.preventDefault(); // Prevent form submission

            const buttonType = event.submitter.getAttribute("name");

            switch (buttonType) {
                case "submit":
                    // Handle submit button click
                    alert("Submit button clicked");
                    break;
                case "draft":
                    // Handle draft button click
                    alert("Save Draft button clicked");
                    break;
                default:
                    // Handle other cases if needed
                    break;
            }
        }

Comments

1

You can try giving name and type to a button and catch it using window.event.submitter.name.

    <button type="submit" name="submit">Submit</button> 
    
    <button type="submit" name="draft">Draft</button> 

    <form onSubmit={handleSubmit} > ...
    const handleSubmit = () => { 
    const buttonType=window.event.submitter.name // will return draft or submit and you can handle it using switch case.

    if(buttonType==="submit"){
    //HANDLE SUBMIT FUNCTION
    return;
    }

    if(buttonType==="draft"){
     //HANDLE DRAFT FUNC
    return;
    }

    }

But this solution doesn't work in safari

Comments

1

I used yup with resolver for validation so my answer might differ. I also used trigger to validate without submitting. I also reset the form so that it won't be marked 'dirty' after saving.

export default function MyForm(props) {
  const {
    control,
    reset,
    trigger,
    handleSubmit,
    getValues,
    formState: { isDirty },
  } = useForm({
    mode: "onBlur",
    reValidateMode: "onBlur",
    shouldUnregister: true,
    defaultValues: {
      name: "",
      id: "",
      //rest of values
    },
    resolver: yupResolver(schema),
  });  


  const handleOnSubmit = async (event) => {
    if(!isDirty){
      //navigate out of page
    } else {
      //save and exit
    }
  }

  const handleOnSave = async () => {
    trigger(); //triggers validation for whole form
    const formValue = getValues();
    const isValid = schema.isValidSync(formValue);
    if(isValid){
      //await save actions
      if(savedSuccessfully){
        reset(formValue);
        //anything else
      }
    }
  };

}

1 Comment

Nice answer with good hints on the useForm API.
0

I stumbled across the same problem, I solved it by adding an onClick event to each submit button with a setValue() function. Example:

import { useForm } from 'react-hook-form';

const { register, handleSubmit, setValue } = useForm();

const onSubmit = (data) => {
    console.log(data.method)
}

<form onSubmit={handleSubmit(onSubmit)}>
    <button type='submit' name='A' {...register('method')} onClick={() => setValue('method', 'A')}>A button</button>
    <button type='submit' name='B' {...register('method')} onClick={() => setValue('method', 'B')}>B button</button>
</form>

Comments

0

I solved this by giving each submit button a name and value attribute. For example, both buttons use name="mode", with value="draft" for Save as Draft and value="submit" for Submit. This allows the form submission handler to determine which action was intended based on the button that triggered the submit.

HTML:

<form onSubmit={form.handleSubmit(onSubmitForm)}>
  <button
    type="submit"
    name="mode"
    value="draft"
  >
    Save as Draft
  </button>

  <button
    type="submit"
    name="mode"
    value="submit"
  >
    Submit
  </button>
</form>

Then, the onSubmitForm function reads the value of the button and calls the correct handler:

// Typescript
const onSubmitForm = (formData: z.infer<typeof newAdjustmentSchema>, event?: React.BaseSyntheticEvent) => {
  const submitter = (event?.nativeEvent as SubmitEvent)?.submitter as HTMLButtonElement | null;
  const mode = submitter?.value;

  if (mode === "draft") {
    saveAsDraft(formData);
  } else {
    submitAdjustment(formData);
  }
}

Comments

-1

I did it in the next way:

onSubmit - form submission handler

                  <Button type="submit">Post</Button>
                  <Button
                    appearance="stroke"
                    onClick={handleSubmit((data) =>
                      onSubmit({
                        ...data,
                        status: CreateResumeRequestStatusEnum.Draft,
                      })
                    )}
                  >
                    Save for later
                  </Button>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.