I have a problem with using The Range Date Picker inside the Form component. To be exact, I need an object to store the {from, to} values of the range, but using an object as a Form field value makes error messages not work. I just get undefined as an error message.
The current fix I'm using, is that I just modified the Form Message Component to render the errors a bit differently, but I think it's more of a hack than the proper way.
The code:
const formSchema = z.object({
title: z.string().min(2, {
message: "Title must be at least 2 characters.",
}),
date: z.object({
from: z.date(),
to: z.date(),
}),
});
function NewEventPage() {
const form = useForm({
resolver: zodResolver(formSchema),
defaultValues: {
title: "",
date: {},
},
});
function onError(a) {
console.log(a);
/*
title:
message: "Title must be at least 2 characters."
ref: {focus: ƒ, select: ƒ, setCustomValidity: ƒ, reportValidity: ƒ}
type: "too_small"
date:
from: {message: 'Required', type: 'invalid_type', ref: undefined}
to: {message: 'Required', type: 'invalid_type', ref: undefined}
*/
}
return (
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit, onError)}
className="mx-auto mt-12 grid max-w-screen-lg grid-cols-2 gap-x-12 gap-y-8"
>
<h1 className="col-span-2 scroll-m-20 text-center text-4xl font-extrabold tracking-tight lg:text-5xl">
Create A New event
</h1>
<FormField
control={form.control}
name="title"
render={({ field }) => {
return (
<FormItem>
<FormLabel>Event Title</FormLabel>
<FormControl>
<Input placeholder="The best title ever" {...field} />
</FormControl>
<FormDescription>Give a name for your event</FormDescription>
<FormMessage />
</FormItem>
);
}}
/>
<FormField
control={form.control}
name="date"
render={({ field }) => (
<FormItem>
<FormLabel>Date</FormLabel>
<FormControl>
<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={cn(
"w-full justify-start text-left font-normal",
!field.value && "text-muted-foreground",
)}
>
<CalendarIcon className="mr-2 h-4 w-4" />
{field.value?.from ? (
field.value.to ? (
<>
{format(field.value.from, "LLL dd, y")} -{" "}
{format(field.value.to, "LLL dd, y")}
</>
) : (
format(field.value.from, "LLL dd, y")
)
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
initialFocus
mode="range"
defaultMonth={field.value?.from}
selected={field.value}
onSelect={field.onChange}
numberOfMonths={2}
/>
</PopoverContent>
</Popover>
</FormControl>
<FormDescription>
Select the date for when the event will take place
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit" className="col-span-2">
Submit
</Button>
</form>
</Form>
);
}
Title shows the error, but date shows undefined:
I have got a solution for this issue, also I have resolved the solution for date picker not saving/maintaining the selected value.
I have updated the UI Selected value will never sets to initial date (major issues resolved with this picker). Stunning UI using shad cn select. Completely customized using shad-cn components You can find the solution at: https://nurture-tech-ebon.vercel.app/blog/how-to-add-year-selection-shadcn image
I have found a solution:
Define "from: and "to" as optional:
z.object({ from: z.date().optional(), to: z.date().optional(), })
Add "SuperRefine" validation:
.superRefine((data, ctx) => { if (data.from === undefined || data.to === undefined) { return ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'Please select a date range.', }) } return data })
Then, since "from" is not optional in the DataRage type, we have to specify that the value that the input is going to receive is of type DateRage, this is just so that typescript does not detect a type error:
<DatePickerRange defaultValue={field.value as DateRange} ... >
The validation would be like this:
const formSchema = z.object({
date_range: z
.object({
from: z.date().optional(),
to: z.date().optional(),
})
.superRefine((data, ctx) => {
if (data.from === undefined || data.to === undefined) {
return ctx.addIssue({
code: z.ZodIssueCode.custom,
message: 'Please select a date range.',
})
}
return data
}),
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With