Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Does anyone know how to conditionally validate form fields? #3561

Open
badddams opened this issue Jun 10, 2024 · 2 comments
Open

Does anyone know how to conditionally validate form fields? #3561

badddams opened this issue Jun 10, 2024 · 2 comments

Comments

@badddams
Copy link

I've been using Zod for about 2 weeks now and I spend way more time googling how to do stuff.

I'm implementing basic form functionality yet Zod feels like it makes it 1000 times more difficult than it needs to be.

I have a form that contains

  • start date
  • end date
  • checkbox (I currently work here)

I want to make the end date required only when the checkbox is false. I am using react-hook-form + zod. Can anyone help?

@patrickJramos
Copy link

patrickJramos commented Jun 12, 2024

you can just refine the object, or if you want a better type on the end, use discriminatedUnion

using refine:

const validator1 = z.object({
  start_date: z.date(),
  end_date: z.date().optional(),
  checkbox: z.boolean()
}).refine(value => {
  if (value.checkbox) {
    return value.end_date != undefined;
  }
  return true;
});

let result = validator1.safeParse({ checkbox: true, start_date: new Date() });
console.log(result); // error

result = validator1.safeParse({ checkbox: false, start_date: new Date() });
if (result.success) {
  console.log(result.data); // success, type of data is { start_date: Date; checkbox: boolean; end_date?: Date | undefined; }
}

using discriminatedUnion:

const withRequiredEnd = z.object({
  start_date: z.date(),
  end_date: z.date(),
  checkbox: z.literal(true)
});

const withOptionalEnd = z.object({
  start_date: z.date(),
  end_date: z.date().optional(),
  checkbox: z.literal(false)
});

const validator2 = z.discriminatedUnion('checkbox', [withRequiredEnd, withOptionalEnd]);

let result2 = validator2.safeParse({ checkbox: true, start_date: new Date() });
console.log(result2); // error

result2 = validator2.safeParse({ checkbox: false, start_date: new Date() });
if (result2.success) {
  console.log(result2.data); // success, type of data is
  // {
  //     checkbox: true;
  //     start_date: Date;
  //     end_date: Date;
  // } | {
  //     checkbox: false;
  //     start_date: Date;
  //     end_date?: Date | undefined;
  // }
}

@jadejr
Copy link

jadejr commented Jun 30, 2024

Perhaps there needs to be a cookbook of examples in the codebase somewhere?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants