T
TanStack13mo ago
fascinating-indigo

Conditionally require field(s) using ZOD

I have some fields that are only required once the user checked a Checkbox Here's a reproduction: https://stackblitz.com/edit/tanstack-form-cuevyr?file=src%2Findex.tsx Questions: 1) Is there a way to react to the Checkbox being checked/unchecked and then setting the "address"-Object to undefined? Is that the way to do it? 2) Why isn't the formErrorMap displaying the Errors?
Pascal Küsgen
StackBlitz
Form Zod Example (forked) - StackBlitz
Run official live example code for Form Zod, created by Tanstack on StackBlitz
4 Replies
fascinating-indigo
fascinating-indigoOP13mo ago
I tried to express my validation rules to the zod schema using .superRefine but it seems this will only be possible once zod v4 is released as .superRefine returns a ZodEffect instead of a ZodObject. What I would do now: - make the address nullish and partial using zod: address: addressSchema.partial().nullish(), - check at the field-level that the inputs are as expected:
<form.Field
name="address.street"
validators={{
onChangeListenTo: ['wantsCdShipped'],
onChange: ({ value, fieldApi }) => {
if (fieldApi.form.getFieldValue('wantsCdShipped') === true) {
const parsed = z.string().min(1, 'Please fill the Street.').safeParse(value);
return parsed.success ? undefined : parsed.error.issues.map((issue) => issue.message).join(', ');
}

return undefined;
},
}}
children={(field) => (
{…}
)} />
<form.Field
name="address.street"
validators={{
onChangeListenTo: ['wantsCdShipped'],
onChange: ({ value, fieldApi }) => {
if (fieldApi.form.getFieldValue('wantsCdShipped') === true) {
const parsed = z.string().min(1, 'Please fill the Street.').safeParse(value);
return parsed.success ? undefined : parsed.error.issues.map((issue) => issue.message).join(', ');
}

return undefined;
},
}}
children={(field) => (
{…}
)} />
That should take care of my validation issue - the formErrorMap shows up - so 2) resolved ✅ The Question remains if there's a way to set the address-Object to undefined when the checkbox changes. Otherwise I'll take care of it in the onSubmit.
stormy-gold
stormy-gold13mo ago
I'm not sure it's too safe, but I'd give it a try with this in the onChange of your checkbox input
onChange={(e) => {
if (!e.target.checked) {
form.setFieldValue('address', undefined);
}
field.handleChange(e.target.checked);
}}
onChange={(e) => {
if (!e.target.checked) {
form.setFieldValue('address', undefined);
}
field.handleChange(e.target.checked);
}}
fascinating-indigo
fascinating-indigoOP13mo ago
After sleeping on it for a night - I think I'll keep the values in the adress-object until it's submitted and allow it to be partial().nullish() - if I set the address to undefined when unchecking the checkbox I'll loose all the inputs the user made. If the user ticks the checkbox again they have to re-enter all the values.
stormy-gold
stormy-gold13mo ago
Wise choice 😄

Did you find this page helpful?