T
TanStack5mo ago
sensitive-blue

Is it possible to alternate between validation schemas depending on the action being performed?

Hi there! I've been trying to find a solution to this problem I'm facing but I feel like I'm hitting a wall here... I have this huge form that needs to be filled manually with data extracted from a PDF file. Right now I'm using a zod schema to run the validation and it's working as expected. The problem comes when I need to add a "Save draft" button, because the "complete" and "draft" versions have different requirements even though they have the the same structure (AKA some of the required fields in the "complete" version are optional for the "draft"). I've created a simple example to showcase this issue and how I'm approaching it: https://codesandbox.io/p/devbox/inspiring-river-forked-94zqlj In this example I created a form that allows writers to publish articles (not really). In order to publish an article it needs a title, a content of length >= 10 and the signature from the author, but those requirements are a bit too strict for saving a draft (only the title is required for saving a draft). The default action of the form is "submit", which just makes sense if we want to show the user the requirements needed to publish an article. The problem with this is that the "Save draft" button won't do anything because the form has errors in it and even though we've changed the validator to the draft one, the form's state.canSubmit is still set to false, and it's not until that we trigger a re-validation (by triggering an onChange in each field, for instance) that we can clear the errors and actually submit the draft. I've tried with other approaches but none of them provided the UX anyone would expect from that form, and seemed way too hacky for such a simple use case.
3 Replies
sensitive-blue
sensitive-blueOP5mo ago
UPDATE: I got it to work by using the canSubmitWhenInvalid option if anyone is facing a similar issue. I was looking for a way to reset the validation (canSubmit & errors basically) on schema change so the validation could be triggered again but couldn't find a way to do that. That would've been a bit more intuitive imo, but the canSubmitWhenInvalid solution was simple enough so I guess that works too
exotic-emerald
exotic-emerald5mo ago
sounds like you want a zod union that determines what each structure requires
z.union([
z.object({
action: z.literal('publish'),
title: z.string().min(3, "Too short!"),
content: z.string().min(10, "The content should be a little bit longer"),
signature: z.string().min(1, "You must provide the author's signature")
}),
z.object({
action: z.literal('draft'),
title: z.string().min(3, "Too short!"),
content: z.string(),
signature: z.string().optional()
})
])
z.union([
z.object({
action: z.literal('publish'),
title: z.string().min(3, "Too short!"),
content: z.string().min(10, "The content should be a little bit longer"),
signature: z.string().min(1, "You must provide the author's signature")
}),
z.object({
action: z.literal('draft'),
title: z.string().min(3, "Too short!"),
content: z.string(),
signature: z.string().optional()
})
])
This can be further refined by taking out the common properties with .and(ZodSchema), but for a form this size it should be alright also note how the form action is now part of the form values, since it's changeable and affects how your form can be submitted
exotic-emerald
exotic-emerald5mo ago
this is the resulting type of this schema
No description

Did you find this page helpful?