Why do conditionally optional inputs do not show error message until all mandatory values are error free? #363
-
Allow me to illustrate what I'm trying to explain. Let's say we have a form with: title = Mandatory Once I fill out the required field which is title, then is when I found out that I must fill out either category or a custom category. What I would like Conform to do is show me both errors at the same time. Because on the schema I'm making sure that either category or custom category should have a value: const schema = z
.object({
title: z.string({
required_error: "Title is required",
invalid_type_error: "Title must be a string",
}),
category: z.string().optional(),
custom_category: z.string().optional(),
})
.transform((data, ctx) => {
console.log(`data on server`, data);
const { category, custom_category } = data;
if (!category && !custom_category) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "Please specify either a category or a custom_category.",
path: ["custom_category"],
});
return null;
}
return data;
}); Is this possible? Here's a codesandbox that illustrates my issue: |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
It's because zod will run To fix this, a common solution is to narrow down the scope of your schema: const schema = z
.object({
title: z.string({
required_error: "Title is required",
invalid_type_error: "Title must be a string",
}),
}).and(
// This schema not does not have title included
z.object({
category: z.string().optional(),
custom_category: z.string().optional(),
})
.transform((data, ctx) => {
console.log(`data on server`, data);
const { category, custom_category } = data;
if (!category && !custom_category) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "Please specify either a category or a custom_category.",
path: ["custom_category"],
});
return null;
}
return data;
})
); This is one of the things I wish zod mentioned in the docs. Many people find this suprising as well. |
Beta Was this translation helpful? Give feedback.
It's because zod will run
.refine()
or.transform()
only if the schema is fulfilled. When you don't have a title provided, what zod see is an empty object (since Conform strip empty string) which doesn't satisfy the type as it expects title to be a string. So it stop running the transform.To fix this, a common solution is to narrow down the scope of your schema: