Skip to content

Commit 710c6e4

Browse files
author
Zabilsya
committed
[DOP-22123] refactor show errors in form from backend
1 parent 1a74995 commit 710c6e4

File tree

5 files changed

+67
-19
lines changed

5 files changed

+67
-19
lines changed

src/shared/config/errors/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ interface DefaultError {
55

66
type LocationTypeError = 'body' | 'query';
77

8-
interface FormFieldError extends DefaultError {
8+
export interface FormFieldError extends DefaultError {
99
location: [Extract<LocationTypeError, 'body'>, string];
1010
}
1111

src/shared/ui/ManagedForm/index.tsx

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { checkIsFormFieldsError, getErrorMessage } from '@shared/config';
77

88
import classes from './styles.module.less';
99
import { ManagedFormProps } from './types';
10+
import { cleanErrors, showErrorsInFields } from './utils';
1011

1112
/** Form component to manage the request and results of a form request */
1213
export const ManagedForm = <T extends object, R>({
@@ -49,11 +50,7 @@ export const ManagedForm = <T extends object, R>({
4950

5051
if (checkIsFormFieldsError(error) && error.response) {
5152
message = 'Form error has occurred';
52-
const fieldErrors = error.response.data.error.details.map((field) => ({
53-
name: field.location[1],
54-
errors: [field.message],
55-
}));
56-
form.setFields(fieldErrors);
53+
showErrorsInFields(form, error.response.data.error.details);
5754
}
5855

5956
notification.error({
@@ -63,20 +60,8 @@ export const ManagedForm = <T extends object, R>({
6360
});
6461
};
6562

66-
// Clean error from backend after field change value
6763
const onValuesChange = (values: T) => {
68-
Object.keys(values).forEach((field) => {
69-
const error = form.getFieldError(field);
70-
if (!error.length) {
71-
return;
72-
}
73-
form.setFields([
74-
{
75-
name: field,
76-
errors: [],
77-
},
78-
]);
79-
});
64+
cleanErrors(form, values);
8065
};
8166

8267
return (
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { FormInstance } from 'antd';
2+
3+
/**
4+
* Util for cleaning field error text from backend while change its value
5+
*
6+
* @param form - Form instance.
7+
* @param values - Form values that have changed.
8+
*
9+
*/
10+
export const cleanErrors = (form: FormInstance, values: object, parentPath: string[] = []): void => {
11+
Object.entries(values).forEach(([key, value]) => {
12+
const currentPath = [...parentPath, key];
13+
14+
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
15+
cleanErrors(form, value, currentPath);
16+
return;
17+
}
18+
const error = form.getFieldError(currentPath);
19+
if (error.length) {
20+
form.setFields([
21+
{
22+
name: currentPath,
23+
errors: [],
24+
},
25+
]);
26+
}
27+
});
28+
};
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './cleanErrors';
2+
export * from './showErrorsInFields';
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { FormFieldError } from '@shared/config';
2+
import { FormInstance } from 'antd';
3+
4+
/**
5+
* Util for processing and displaying form field errors from backend
6+
*
7+
* @param form - Form instance
8+
* @param errors - Array of objects with paths to fields contains an error from backend
9+
*
10+
*/
11+
export const showErrorsInFields = (form: FormInstance, errors: FormFieldError[]): void => {
12+
const fieldErrors = errors
13+
.map((field) => {
14+
// Keep only valid parts of the path
15+
const validPath = field.location.reduce<string[]>((acc, key) => {
16+
const currentPath = [...acc, key];
17+
// Check if the path to the current key exists
18+
if (typeof form.getFieldValue(currentPath) === 'object' || form.getFieldInstance(currentPath)) {
19+
acc.push(key);
20+
}
21+
return acc;
22+
}, []);
23+
24+
return {
25+
name: validPath,
26+
errors: [field.message],
27+
};
28+
})
29+
// Remove errors without a valid path
30+
.filter(({ name }) => name.length > 0);
31+
32+
form.setFields(fieldErrors);
33+
};

0 commit comments

Comments
 (0)