Skip to content

Commit

Permalink
feat(ui-common): display submit error in Form
Browse files Browse the repository at this point in the history
  • Loading branch information
skamril committed Jul 24, 2023
1 parent 6b16e01 commit 92d5a1e
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 6 deletions.
35 changes: 29 additions & 6 deletions webapp/src/components/common/Form/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,15 @@ import clsx from "clsx";
import { LoadingButton, LoadingButtonProps } from "@mui/lab";
import UndoIcon from "@mui/icons-material/Undo";
import RedoIcon from "@mui/icons-material/Redo";
import axios from "axios";
import useEnqueueErrorSnackbar from "../../../hooks/useEnqueueErrorSnackbar";
import useDebounce from "../../../hooks/useDebounce";
import { getDirtyValues, stringToPath, toAutoSubmitConfig } from "./utils";
import {
ROOT_ERROR_KEY,
getDirtyValues,
stringToPath,
toAutoSubmitConfig,
} from "./utils";
import useDebouncedState from "../../../hooks/useDebouncedState";
import usePrompt from "../../../hooks/usePrompt";
import { mergeSxProp } from "../../../utils/muiUtils";
Expand Down Expand Up @@ -125,14 +131,17 @@ function Form<TFieldValues extends FieldValues, TContext>(
: config?.defaultValues,
});

const { getValues, setValue, handleSubmit, formState, reset } = formApi;
const { getValues, setValue, setError, handleSubmit, formState, reset } =
formApi;
// * /!\ `formState` is a proxy
const { isSubmitting, isSubmitSuccessful, isDirty, dirtyFields } = formState;
const { isSubmitting, isSubmitSuccessful, isDirty, dirtyFields, errors } =
formState;
// Don't add `isValid` because we need to trigger fields validation.
// In case we have invalid default value for example.
const isSubmitAllowed = isDirty && !isSubmitting;
const showSubmitButton = !hideSubmitButton && !autoSubmitConfig.enable;
const showFooter = showSubmitButton || enableUndoRedo;
const rootError = errors.root?.[ROOT_ERROR_KEY];

const formApiPlus = useFormApiPlus({
formApi,
Expand Down Expand Up @@ -242,8 +251,17 @@ function Form<TFieldValues extends FieldValues, TContext>(
}

return Promise.all(res)
.catch((error) => {
enqueueErrorSnackbar(t("form.submit.error"), error);
.catch((err) => {
enqueueErrorSnackbar(t("form.submit.error"), err);

// Any error under the `root` key are not persisted with each submission.
// They will be deleted automatically.
// cf. https://www.react-hook-form.com/api/useform/seterror/
setError(`root.${ROOT_ERROR_KEY}`, {
message: axios.isAxiosError(err)
? err.response?.data.description
: err?.toString(),
});
})
.finally(() => {
preventClose.current = false;
Expand Down Expand Up @@ -306,8 +324,13 @@ function Form<TFieldValues extends FieldValues, TContext>(
<FormProvider {...formApiPlus}>{children}</FormProvider>
)}
</FormContext.Provider>
{rootError && (
<Box color="error.main" sx={{ fontSize: "0.9rem", mb: 2 }}>
{rootError.message || t("form.submit.error")}
</Box>
)}
{showFooter && (
<Box sx={{ display: "flex" }}>
<Box sx={{ display: "flex" }} className="Form__Footer">
{showSubmitButton && (
<>
<LoadingButton
Expand Down
2 changes: 2 additions & 0 deletions webapp/src/components/common/Form/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,5 @@ export function stringToPath(input: string): string[] {
.split(/\.|\[/)
.filter(Boolean);
}

export const ROOT_ERROR_KEY = "default";

0 comments on commit 92d5a1e

Please sign in to comment.