How to submit with React Hook Form when having mode onBlur? - reactjs

This is not like what this question is asking.
Basically, I have a form that I want to auto-submit whenever fields are changed. I.e. I do not want a submit button.
So, having this:
const {
formState,
handleSubmit
} = useForm<TSaveInputSchema>({
mode: "onBlur",
reValidateMode: "onChange",
criteriaMode: "firstError",
resolver: zodResolver(saveInputSchema),
});
const handleSave = useCallback<HandleSaveCallback>(
(data) => {
console.log("DATA SUBMIT", data);
}
), []);
And HTML like this:
<form onSubmit={handleSubmit(handleSave)}>
<input {...register("name")} />
</form>
does not call the handleSave function when the input field is blurred.
How can this be done, if possible? Or do I have to manually trigger the submit through other means (e.g. using useEffect)?

Too much refactor for the day, the solution was dumb:
Replace
<form onSubmit={handleSubmit(handleSave)}>
<input {...register("name")} />
</form>
with
<input {...register("name", { onBlur:handleSubmit(handleSave) )} />

Related

Prevent function from running when a variable changes in React

I have a form with a checkbox and text input.
const [formVars, setFormVars] = useState<any>({checkbox:true})
const submitForm = () => {
console.log({formVars})
}
render (
<Checkbox checked={formVars.checkbox} /> Bake the cookies?
<TextInput label="what kind of cookies?" />
<Button onClick={() => submitForm()}
)
submitForm should not run until the user clicks submit, however my code seems to be producing a never-ending loop where the form changes formVars, and the change sets off submitForm. How can I prevent this?
There are a bunch of typos in the question, so I created a simple copy of your code.
The button's onClick prop takes a callback, not a function call. You're likely calling the submit function instead of passing it to the button onClick prop.
Here's how you trigger the submission manually for controlled inputs
export default function App() {
const [formVars, setFormVars] = useState({ checkbox: true });
const submitForm = (e) => {
console.log({ formVars });
};
const handleChange = (e) => {
setFormVars(e.target.value);
};
return (
<>
<label>
Name:
<input onChange={handleChange} type="text" name="name" />
</label>
<button onClick={submitForm}>submit</button>
</>
);
}
<Button onClick={()=> submitForm}
Try this syntax for the button

React-hook-from form inside one. How to do indepentdend second form?

I have a main form and also have a second form block to check registered or not in one payment service.
When I click on the button Check, triggering the main form and sends data. The second form also sends data. I want to just check when I click on the button inside the second form. How to handle this, can you help?
const { register, handleSubmit, errors, control } = useForm({
mode: {
onblur,
},
});
const {
register: register2, handleSubmit: handleSubmit2, errors: errors2, control: control2,
} = useForm({
mode: {
onblur,
}
});
const onSubmit = (data) => {
console.log(data);
};
const onSubmit2 = (data) => {
console.log(data);
};
<form onSubmit={handleSubmit(onSubmit)}>
<Controller
as={InputMask}
control={control}
mask="+\9\98 99 999 99 99"
name="phone"
id="phone"
defaultValue={phone}
required
/>
<form
onSubmit={
handleSubmit2(onSubmit2)
}
>
<Controller
as={InputMask}
control={control2}
mask="+\9\98 99 999 99 99"
name="phone_alif"
id="phone_alif"
required
/>
<button>Check</button>
</form>
<button>Send</button>
</form>
I solved. In order to not triggering the main form use onClick event listener on the Check button.
<form>
<Controller
as={InputMask}
control={control2}
mask="+\9\98 99 999 99 99"
name="phone_alif"
id="phone_alif"
required
/>
<button onClick={handleSubmit2(onSubmit2)}>
Check
</button>
</form>

formik how to trigger submit from outside

I got a form like this
const SubtitleForm = ({ sub }) => {
const formik: any = useFormik({
initialValues: sub,
onSubmit: async (values) => {
const res = await update(values)
},
})
return (
<form className="subtitleFormComponent">
<input
className="subtitle"
autoComplete="off"
type="text"
name="name"
onChange={formik.handleChange}
value={formik.values.name}
/>
</form>
)
}
export default SubtitleForm
How can I trigger submit from outside this form / component ?
If you meant to have the submit button in a different component to the fields; I'd suggest to wrap both in the form. Then, you can use the useFormikContext in the inputs to update the data, and in the submit button.
A POC of the idea:
https://codesandbox.io/s/sharp-chebyshev-5nonm?file=/src/App.js

Get the values in the form, from a component outside the form

I've a component that is built using react-hook-form. I'm trying access the value in form, through a button that is sibling of the Form component. Basically the getvalue function should somehow get the values in the form.
Form.tsx
export default function Form({ onSubmit }) {
const { register, handleSubmit } = useForm({
defaultValues: {
firstName: "bill",
lastName: "luo",
email: "bluebill1049#hotmail.com"
}
});
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register("firstName")} />
<input {...register("lastName")} />
<input {...register("email")} />
<button type="submit">Submit</button>
</form>
)
}
App.tsx
const onSubmit = data => console.log(data);
const getValue = ???
function App() {
return (
<Form onSubmit={onSubmit}/>
<button onClick={getValue} />
)
}
I want to get the form data values in getValue
You could use onChange to set the values in the form
<Form onSubmit={onSubmit} geValue={getValue}/>
and inside the Form.tsx
<form onSubmit={handleSubmit(onSubmit)} onChange={handleChange(getValue)}>
however i'm not really sure if this would work for you - can you elaborate more about what you are trying to do, maybe we can help you better.
Also, you should only pass callbacks to onSubmit and onChange so probably this is the correct syntax for that
<form onSubmit={(e) => handleSubmit(e, onSubmit)} onChange={(e) => handleChange(e, getValue)}>

React JS Multiple submit Buttons react-hook-form

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>
I had the same problem and I resolved it the following way:
I have two buttons, the first bottom 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 to save and one 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!
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>
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>
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
}
}
};
}
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
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>

Resources