Skip to content

Commit 26fdf66

Browse files
Georgi2704Georgi2704
andauthored
2286: Form validation issues fix (#198)
* Fix validation error not resetting when form field has change * Validation error improvements * Add changeset --------- Co-authored-by: Georgi2704 <[email protected]>
1 parent 0153b7b commit 26fdf66

File tree

5 files changed

+74
-3
lines changed

5 files changed

+74
-3
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'pydantic-forms': minor
3+
---
4+
5+
Fix validation error not resetting when form field has change

frontend/packages/pydantic-forms/src/core/PydanticFormHandler.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export const PydanticFormHandler = ({
6262
isLoading,
6363
pydanticFormSchema,
6464
defaultValues,
65+
handleRemoveValidationError,
6566
} = usePydanticForm(
6667
formKey,
6768
formId,
@@ -110,6 +111,7 @@ export const PydanticFormHandler = ({
110111
onPrevious={onPrevious}
111112
pydanticFormSchema={pydanticFormSchema}
112113
title={title}
114+
handleRemoveValidationError={handleRemoveValidationError}
113115
/>
114116
</PydanticFormValidationErrorContext.Provider>
115117
);

frontend/packages/pydantic-forms/src/core/ReactHookForm.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* Here we define the outline of the form
77
*/
8-
import React from 'react';
8+
import React, { useEffect } from 'react';
99
import type { FieldValues } from 'react-hook-form';
1010
import { FormProvider, useForm } from 'react-hook-form';
1111

@@ -36,6 +36,7 @@ export interface ReactHookFormProps {
3636
onPrevious: () => void;
3737
pydanticFormSchema?: PydanticFormSchema;
3838
title?: string;
39+
handleRemoveValidationError: (location: string) => void;
3940
}
4041

4142
export const ReactHookForm = ({
@@ -51,6 +52,7 @@ export const ReactHookForm = ({
5152
onPrevious,
5253
pydanticFormSchema,
5354
title,
55+
handleRemoveValidationError,
5456
}: ReactHookFormProps) => {
5557
const config = useGetConfig();
5658
const t = useTranslations('renderForm');
@@ -73,6 +75,13 @@ export const ReactHookForm = ({
7375
values: initialValues || defaultValues,
7476
});
7577

78+
useEffect(() => {
79+
const reactHookFormWatch = reactHookForm.watch(
80+
(_, { name }) => name && handleRemoveValidationError(name),
81+
);
82+
return reactHookFormWatch.unsubscribe;
83+
}, [handleRemoveValidationError, reactHookForm]);
84+
7685
if (apiError) {
7786
console.error('API Error:', apiError);
7887
return ErrorComponent;

frontend/packages/pydantic-forms/src/core/WrapFieldElement.tsx

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,21 @@ import React from 'react';
22
import { Controller, useFormContext } from 'react-hook-form';
33

44
import { FieldWrap } from '@/components/fields';
5-
import type { PydanticFormControlledElement, PydanticFormField } from '@/types';
5+
import { useGetValidationErrors } from '@/core/hooks';
6+
import {
7+
PydanticFormControlledElement,
8+
PydanticFormField,
9+
PydanticFormValidationErrorDetails,
10+
} from '@/types';
11+
12+
const getValidationErrorMsg = (
13+
errorResponse: PydanticFormValidationErrorDetails | null,
14+
path: string,
15+
): string | undefined => {
16+
return errorResponse?.source?.find(
17+
(err) => err.loc.map(String).join('.') === path,
18+
)?.msg;
19+
};
620

721
export const WrapFieldElement = ({
822
PydanticFormControlledElement,
@@ -14,6 +28,8 @@ export const WrapFieldElement = ({
1428
extraTriggerFields?: string[];
1529
}) => {
1630
const { control, trigger } = useFormContext();
31+
const validationErrorDetails = useGetValidationErrors();
32+
1733
return (
1834
<Controller
1935
name={pydanticFormField.id}
@@ -32,7 +48,12 @@ export const WrapFieldElement = ({
3248
<FieldWrap
3349
pydanticFormField={pydanticFormField}
3450
isInvalid={fieldState.invalid}
35-
frontendValidationMessage={fieldState.error?.message}
51+
frontendValidationMessage={
52+
getValidationErrorMsg(
53+
validationErrorDetails,
54+
pydanticFormField.id,
55+
) ?? fieldState.error?.message
56+
}
3657
>
3758
<PydanticFormControlledElement
3859
onChange={onChangeHandle}

frontend/packages/pydantic-forms/src/core/hooks/usePydanticForm.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,34 @@ export interface UsePydanticFormReturn {
2525
isSending: boolean;
2626
pydanticFormSchema?: PydanticFormSchema;
2727
defaultValues: FieldValues;
28+
handleRemoveValidationError: (location: string) => void;
2829
}
2930

31+
const removeValidationErrorByLoc = (
32+
validationErrors: PydanticFormValidationErrorDetails | null,
33+
locToRemove: string,
34+
): PydanticFormValidationErrorDetails | null => {
35+
if (!validationErrors) return null;
36+
37+
const newSource = validationErrors.source.filter((err) => {
38+
const locPath = err.loc.join('.'); // e.g. "contact_persons.0.email"
39+
return locPath !== locToRemove;
40+
});
41+
42+
const [topKey] = locToRemove.split('.'); // e.g. "contact_persons"
43+
const newMapped = { ...validationErrors.mapped };
44+
45+
if (topKey && newMapped[topKey]) {
46+
delete newMapped[topKey];
47+
}
48+
49+
return {
50+
...validationErrors,
51+
source: newSource,
52+
mapped: newMapped,
53+
};
54+
};
55+
3056
export function usePydanticForm(
3157
formKey: string,
3258
formId: string,
@@ -131,6 +157,13 @@ export function usePydanticForm(
131157
// eslint-disable-next-line react-hooks/exhaustive-deps
132158
}, [apiResponse]);
133159

160+
const handleRemoveValidationError = (location: string) => {
161+
setValidationErrorsDetails((prev) => {
162+
const updatedErrors = removeValidationErrorByLoc(prev, location);
163+
return updatedErrors;
164+
});
165+
};
166+
134167
return {
135168
validationErrorsDetails,
136169
apiError,
@@ -140,5 +173,6 @@ export function usePydanticForm(
140173
pydanticFormSchema,
141174
defaultValues,
142175
isSending,
176+
handleRemoveValidationError,
143177
};
144178
}

0 commit comments

Comments
 (0)