There is a state that can take the values true or false. If state is true, the field is required, otherwise it is not. How to validate depending on the condition? I found an example:
const [selectOption, setSelectOption] = useState(null);
const stepTwoForm = useForm({
resolver: zodResolver(stepTwoSchema.refine(
(data) => ({ ...data, select: selectOption }),
)),
});
And then
export const stepTwoSchema = z.object({
inputOne: z.string().optional(),
inputTwo: z.string().optional(),
}).superRefine((data, ctx) => {
const selectedOption = ctx.parent?.select;
if (selectedOption === 'A' && !data.inputOne?.trim()) {
ctx.addIssue({
path: ['inputOne'],
message: 'Input 1 is required when Option A is selected.',
});
}
if (selectedOption === 'B' && !data.inputTwo?.trim()) {
ctx.addIssue({
path: ['inputTwo'],
message: 'Input 2 is required when Option B is selected.',
});
}
});
But this is for the old version of zod. In the new version, ctx does not have the 'parent' property.
There is a state that can take the values true or false. If state is true, the field is required, otherwise it is not. How to validate depending on the condition? I found an example:
const [selectOption, setSelectOption] = useState(null);
const stepTwoForm = useForm({
resolver: zodResolver(stepTwoSchema.refine(
(data) => ({ ...data, select: selectOption }),
)),
});
And then
export const stepTwoSchema = z.object({
inputOne: z.string().optional(),
inputTwo: z.string().optional(),
}).superRefine((data, ctx) => {
const selectedOption = ctx.parent?.select;
if (selectedOption === 'A' && !data.inputOne?.trim()) {
ctx.addIssue({
path: ['inputOne'],
message: 'Input 1 is required when Option A is selected.',
});
}
if (selectedOption === 'B' && !data.inputTwo?.trim()) {
ctx.addIssue({
path: ['inputTwo'],
message: 'Input 2 is required when Option B is selected.',
});
}
});
But this is for the old version of zod. In the new version, ctx does not have the 'parent' property.
Share Improve this question edited Mar 31 at 12:38 Александр Кос asked Mar 31 at 9:32 Александр КосАлександр Кос 1321 silver badge9 bronze badges2 Answers
Reset to default 2To validate fields conditionally in Zod, you have two main approaches:
Include the condition in the form data:
const schema = z.object({ selectOption: z.string(), // Your condition inputOne: z.string().optional(), inputTwo: z.string().optional() }).superRefine((data, ctx) => { if (data.selectOption === "A" && !data.inputOne?.trim()) { ctx.addIssue({ code: "custom", path: ["inputOne"], message: "Input 1 is required for Option A" }); } // Similar for other conditions }); // Usage: useForm({ resolver: zodResolver(schema) });
Pass the condition as a parameter:
const createSchema = (selectOption) => z.object({ inputOne: z.string().optional(), inputTwo: z.string().optional() }).superRefine((data, ctx) => { if (selectOption === "A" && !data.inputOne?.trim()) { ctx.addIssue({/*...*/}); } // Other conditions }); // Usage: useForm({ resolver: zodResolver(createSchema(currentSelection)) });
Choose based on whether the condition is part of your form state or external and handle the
selectOption
data, either include the condition in your form data or pass it externally.
In this scenario, I would simply move selectOption to be inside your schema. You can then access the value from data in your .refine() or .superRefine() function.