Single Submission Handler
Sometimes it's better to seperate your forms, for example if:
- they deal with different concerns
- it should be possible to save them independently
- they are placed inside a wizard
In some cases you might have to connect them back together in order to submit all forms at once. As an example you could have multiple forms which can be saved independently and then also a Save All button, to trigger submission for all forms.
useMergedSubmit
useMergedSubmit
is a custom hook, that returns a function which is similar to the handleSubmit
returned by useFluentForm
.
It receives any amount of fluent form instances as paramater:
import { useCallback, useRef } from "react";
import { UseFluentForm } from "react-fluent-form";
export function useMergedSubmit(...fluentForms: UseFluentForm<any>[]) {
const successCallbackRef = useRef<Function>(() => undefined);
const failureCallbackRef = useRef<Function>(() => undefined);
const handleSubmit = useCallback(
(
success: Function = () => undefined,
failure: Function = () => undefined
) => {
successCallbackRef.current = success;
failureCallbackRef.current = failure;
return async (e: any) => {
if (typeof e === "object") {
if (typeof e.preventDefault === "function") {
e.preventDefault();
}
if (typeof e.stopPropagation === "function") {
e.stopPropagation();
}
}
const submitPromises: Promise<boolean>[] = [];
for (let i = 0; i < fluentForms.length; i++) {
const currentForm = fluentForms[i];
const currentPromise = new Promise<boolean>((resolve) => {
currentForm.handleSubmit(
() => resolve(true),
() => resolve(false)
)(e);
});
submitPromises.push(currentPromise);
}
const results: boolean[] = await Promise.all(submitPromises).catch(() =>
failure()
);
const successful = results.every((results) => results);
successful
? successCallbackRef.current()
: failureCallbackRef.current();
};
},
[fluentForms]
);
return handleSubmit;
}
Example
Following example contains two seperate forms: one for personal details and another for address details.
The handleSubmit
function returned by useMergedSubmit
can be called with with a success/failure callback and triggered via e.g. a button click:
const personalForm = useFluentForm(personalConfig);
const addressForm = useFluentForm(addressConfig);
const handleSubmit = useMergedSubmit(
personalForm,
addressForm
/* add any amount of forms */
);
// will be called if there is no error in every form
const handleSubmitSuccess = () => {
console.log(personalForm.values);
console.log(addressForm.values);
};
// will be called if there is at least one error in any form
const handleSubmitFailure = () => {
console.log(personalForm.errors);
console.log(addressForm.errors);
};
return (
// render forms ...
<button onClick={handleSubmit(handleSubmitSuccess, handleSubmitFailure)} />
);