Last active
March 9, 2025 07:58
-
-
Save AndersonNascimentoDosSantos/b3b8f760f3a431fe9e0ee440f5b0e2d4 to your computer and use it in GitHub Desktop.
Zod image validation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use client"; | |
import { Button } from "@/components/ui/button"; | |
import { | |
Form, | |
FormControl, | |
FormField, | |
FormItem, | |
FormLabel, | |
FormMessage, | |
} from "@/components/ui/form"; //shadcn ui folder | |
import { cn } from "@/lib/utils"; | |
import { zodResolver } from "@hookform/resolvers/zod"; | |
import { useState } from "react"; | |
import { useForm } from "react-hook-form"; | |
import { BsImages, BsPaperclip } from "react-icons/bs"; | |
import { IoSendOutline } from "react-icons/io5"; | |
import * as z from "zod"; | |
const MAX_FILE_SIZE = 1024 * 1024 * 5; | |
const ACCEPTED_IMAGE_MIME_TYPES = [ | |
"image/jpeg", | |
"image/jpg", | |
"image/png", | |
"image/webp", | |
]; | |
const ACCEPTED_IMAGE_TYPES = ["jpeg", "jpg", "png", "webp"]; | |
const formSchema = z.object({ | |
adImage: z | |
.any() | |
.refine((files) => { | |
return files?.[0]?.size <= MAX_FILE_SIZE; | |
}, `Max image size is 5MB.`) | |
.refine( | |
(files) => ACCEPTED_IMAGE_MIME_TYPES.includes(files?.[0]?.type), | |
"Only .jpg, .jpeg, .png and .webp formats are supported." | |
), | |
}); | |
export type ContactFormData = z.infer<typeof formSchema>; | |
export default function Home() { | |
const [selectedImage, setSelectedImage] = useState<File | null>(null); | |
const form = useForm<ContactFormData>({ | |
resolver: zodResolver(formSchema), | |
defaultValues: { | |
adImage: undefined, | |
}, | |
}); | |
const onSubmit = async (data: ContactFormData) => { | |
console.log(data); | |
}; | |
return ( | |
<main className="flex min-h-screen flex-col items-center justify-between p-24"> | |
<Form {...form}> | |
<form onSubmit={form.handleSubmit(onSubmit)}> | |
<div className={cn("flex md:flex-row w-[100%] gap-4 flex-col")}> | |
<div className="flex w-[100%] gap-4 flex-col "> | |
<FormLabel>your form title</FormLabel> | |
<div | |
className={`flex w-[100%] gap-4 p-4 rounded border border-neutral-200 flex-col items-center md:flex-row md:justify-between md:items-center`} | |
> | |
<div | |
className={`flex md:flex-[1] h-[fit-content] md:p-4 md:justify-between md:flex-row | |
`} | |
> | |
{selectedImage ? ( | |
<div className="md:max-w-[200px]"> | |
<img | |
src={URL.createObjectURL(selectedImage)} | |
alt="Selected" | |
/> | |
</div> | |
) : ( | |
<div className="inline-flex items-center justify-between"> | |
<div className="p-3 bg-slate-200 justify-center items-center flex"> | |
<BsImages size={56} /> | |
</div> | |
</div> | |
)} | |
</div> | |
<FormField | |
control={form.control} | |
name="adImage" | |
render={({ field }) => ( | |
<FormItem> | |
<FormControl> | |
<Button size="lg" type="button"> | |
<input | |
type="file" | |
className="hidden" | |
id="fileInput" | |
accept="image/*" | |
onBlur={field.onBlur} | |
name={field.name} | |
onChange={(e) => { | |
field.onChange(e.target.files); | |
setSelectedImage(e.target.files?.[0] || null); | |
}} | |
ref={field.ref} | |
/> | |
<label | |
htmlFor="fileInput" | |
className="bg-blue-500 hover:bg-blue-600 text-neutral-90 rounded-md cursor-pointer inline-flex items-center" | |
> | |
<BsPaperclip /> | |
<span className="whitespace-nowrap"> | |
choose your image | |
</span> | |
</label> | |
</Button> | |
</FormControl> | |
{/* <FormDescription>This is your public display email.</FormDescription> */} | |
<FormMessage /> | |
</FormItem> | |
)} | |
/> | |
</div> | |
</div> | |
</div> | |
<div className={cn("flex w-[100%] gap-4 justify-end")}> | |
<div className="space-y-2"> | |
<Button className="gap-1 py-4 px-4" type="submit"> | |
<span>SUBMIT</span> | |
<IoSendOutline /> | |
</Button> | |
</div> | |
</div> | |
</form> | |
</Form> | |
</main> | |
); | |
} |
@rudy128
i tried to edit you code to a better reading but it did not work well,
all images you shared are private and i couldn't see any of then
can you share they again?
most of the difference i see in your code was this piece
const form = useForm<z.infer>({ resolver: zodResolver(formSchema), defaultValues: { productName: "", productDescription: "", productImage: undefined }, })
where you may received a error of "you're using a function/value as type" or something similar to it
Thank you!
However, if I want to check if the file is uploaded in the first, the resolved error message would be "Max document size is 10MB." instead of "Document is required.".
Here's the code I'm using:
document: z .any() .refine( (files) => !files || files?.length === 0, "Document is required." ) .refine((files) => { return files?.[0]?.size <= MAX_DOCUMENT_FILE_SIZE; }, `Max document size is 10MB.`) .refine( (files) => ACCEPTED_DOCUMENT_MIME_TYPES.includes(files?.[0]?.type), "Only .pdf format is supported." ),
here is for file required
.refine((files) => files?.length !== 0, 'Document is required')
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thankyou,,! Although it didn't work.. I was constantly running into errors.. so I have to hand it over to a senior dev