Skip to content

Commit 2b0dbe4

Browse files
author
Ruben van Leeuwen
committed
1785: Adds nested clientside validations on object fields
1 parent 1144d18 commit 2b0dbe4

File tree

1 file changed

+54
-23
lines changed

1 file changed

+54
-23
lines changed

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

Lines changed: 54 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,61 @@
1010
import { useMemo } from 'react';
1111
import { useForm } from 'react-hook-form';
1212

13-
import { z } from 'zod';
13+
import { ZodRawShape, z } from 'zod';
1414

1515
import { getClientSideValidationRule } from '@/components/componentMatcher';
16-
import { getFlatFieldMap } from '@/core/helper';
1716
import {
1817
CustomValidationRule,
18+
Properties,
1919
PydanticFormSchema,
2020
PydanticFormsContextConfig,
2121
} from '@/types';
2222

23+
/**
24+
* Generates a Zod validation object from an array of Pydantic form fields.
25+
*
26+
* @param pydanticFormFields - An array of Pydantic form fields.
27+
* @returns A ZodRawShape object representing the validation schema.
28+
*/
29+
const getZodValidationObject = (
30+
properties: Properties,
31+
rhf?: ReturnType<typeof useForm>,
32+
customValidationRule?: CustomValidationRule,
33+
customComponentMatcher?: PydanticFormsContextConfig['componentMatcher'],
34+
) => {
35+
const pydanticFormFields = Object.values(properties);
36+
if (!pydanticFormFields) return {};
37+
38+
const validationObject: ZodRawShape = {};
39+
40+
pydanticFormFields.forEach((pydanticFormField) => {
41+
const id =
42+
pydanticFormField.id.split('.').pop() || pydanticFormField.id;
43+
44+
if (pydanticFormField.type === 'object') {
45+
validationObject[id] = z.object(
46+
getZodValidationObject(
47+
pydanticFormField.properties || {},
48+
rhf,
49+
customValidationRule,
50+
customComponentMatcher,
51+
),
52+
);
53+
} else {
54+
const fieldRules =
55+
customValidationRule?.(pydanticFormField, rhf) ??
56+
getClientSideValidationRule(
57+
pydanticFormField,
58+
rhf,
59+
customComponentMatcher,
60+
);
61+
62+
validationObject[id] = fieldRules;
63+
}
64+
});
65+
return validationObject;
66+
};
67+
2368
export const useGetZodValidator = (
2469
pydanticFormSchema?: PydanticFormSchema,
2570
rhf?: ReturnType<typeof useForm>,
@@ -31,26 +76,12 @@ export const useGetZodValidator = (
3176
return z.object({});
3277
}
3378
// Get all fields ids including the nested ones to generate the correct validation schema
34-
const flatFieldMap = getFlatFieldMap(pydanticFormSchema.properties);
35-
36-
return z.object(
37-
[...flatFieldMap].reduce(
38-
(validationObject, [propertyId, pydanticFormField]) => {
39-
const fieldRules =
40-
customValidationRule?.(pydanticFormField, rhf) ??
41-
getClientSideValidationRule(
42-
pydanticFormField,
43-
rhf,
44-
customComponentMatcher,
45-
);
46-
47-
return {
48-
...validationObject,
49-
[propertyId]: fieldRules,
50-
};
51-
},
52-
{},
53-
),
79+
const validationObject = getZodValidationObject(
80+
pydanticFormSchema.properties,
81+
rhf,
82+
customValidationRule,
83+
customComponentMatcher,
5484
);
55-
}, [customValidationRule, rhf, pydanticFormSchema, customComponentMatcher]);
85+
return z.object(validationObject);
86+
}, [customComponentMatcher, customValidationRule, pydanticFormSchema, rhf]);
5687
};

0 commit comments

Comments
 (0)