Best way to validate multiple files via Zod & RHF

So I am adding validation to a form and I want to validate as much as possible on the frontend. Now I do believe some validation needs to be done by the backend, but I'll handle that after I've figured out what already has been validated by the frontend. The things I want to validate are the following: - The user has selected/uploaded at least 3 files for the form - The files are of a accepted file type - The combined size of all files does not exceed a certain threshold My initial thought was to just add the following to the form schema:
image: z.any().array().min(3, { message: "At least 3 files are required" }),
image: z.any().array().min(3, { message: "At least 3 files are required" }),
But the files are not in an array, they are instead bundled in an object like so:
"image": {
"0": {},
"1": {},
"2": {}
}
"image": {
"0": {},
"1": {},
"2": {}
}
So the first hurdle becomes how do I translate this into a Zod shape? This doesn't work
image: z.object({string: z.string(), fileBlob: z.any()})
image: z.object({string: z.string(), fileBlob: z.any()})
And is there a better way to select a specific file and perform operations, eg: formInput.image?.[1].type The data comes from a simple input
<input
type="file"
multiple
{...register("image")}
disabled={isSubmitting}
accept=".jpg, .jpeg, .png, .webp, .mp4"
/>
<input
type="file"
multiple
{...register("image")}
disabled={isSubmitting}
accept=".jpg, .jpeg, .png, .webp, .mp4"
/>
Most of the examples I've seen online are mainly focused around single files and make the assumption that formInput.image?.[0] exists.
8 Replies
Neto
Neto3y ago
You can use preprocess on zod to transform the object into an array
cornflour
cornflour3y ago
for the first part of the question, maybe use z.record?
Neto
Neto3y ago
Or You can parse on the submit handler to pass only the array
Mordi
MordiOP3y ago
yeah records seems to make things a lot simpler The most advanced Zod things I've looked into are .refine and .superrefine, how would the .preprocess look? .preprocess((val) => ???
Neto
Neto3y ago
the type T is just a lazy way of casting where are the 'data' and z.string() you would change for the file and etc
Neto
Neto3y ago
Mordi
MordiOP3y ago
I see , thanks for the help!
Neto
Neto3y ago
happy
Want results from more Discord servers?
Add your server