- Published on
How to use shadcn/ui Range Date Picker inside Form?
- Authors
- Name
- Ripal & Zalak
How to Use Shadcn/UI Range Date Picker Inside Forms
Integrating the Shadcn/UI Range Date Picker into a React Hook Form can be challenging, especially when dealing with object-based values like {from, to}
for date ranges. This guide provides a clear solution to implement and validate the Range Date Picker within your forms effectively.
Common Issues
- Validation Errors: Using objects as form field values can lead to issues where error messages are undefined.
- State Management: Maintaining the selected range without resetting values can be tricky.
- Error Display: Errors may not propagate correctly from nested fields like
date.from
ordate.to
.
The Solution
Follow these steps to seamlessly integrate the Shadcn/UI Range Date Picker into your form.
Step 1: Define the Form Schema
Use zod
to define a schema with validation rules for the range picker. For example:
const formSchema = z.object({
title: z.string().min(2, { message: 'Title must be at least 2 characters.' }),
date: z
.object({
from: z.date().optional(),
to: z.date().optional(),
})
.superRefine((data, ctx) => {
if (!data.from || !data.to) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: 'Please select a complete date range.',
})
}
}),
})
Here, the superRefine
method ensures proper validation for the from
and to
fields.
Step 2: Initialize the Form
Set up the form using react-hook-form
and integrate the schema with a resolver:
const form = useForm({
resolver: zodResolver(formSchema),
defaultValues: {
title: '',
date: { from: undefined, to: undefined },
},
})
Step 3: Render the Range Picker Component
Utilize the Shadcn/UI Range Picker component within the form. Update the selected value and ensure proper validation by binding it to the form field.
<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?.from && 'text-muted-foreground'
)}
>
<CalendarIcon className="mr-2 h-4 w-4" />
{field.value?.from && field.value?.to
? `${format(field.value.from, 'LLL dd, yyyy')} - ${format(
field.value.to,
'LLL dd, yyyy'
)}`
: 'Pick a date range'}
</Button>
</PopoverTrigger>
<PopoverContent align="start">
<Calendar
mode="range"
selected={field.value}
onSelect={field.onChange}
numberOfMonths={2}
/>
</PopoverContent>
</Popover>
</FormControl>
<FormDescription>Select the date range for your event.</FormDescription>
<FormMessage />
</FormItem>
)}
/>
Step 4: Handle Form Submission
Implement the form submission handler to log or process the form values:
function onSubmit(values) {
console.log(values)
}
function onError(errors) {
console.error(errors)
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit, onError)}>
{/* Other form fields */}
<Button type="submit">Submit</Button>
</form>
</Form>
)
FAQs
Why does the error message show as undefined for the date field?
This occurs because nested fields like date.from
and date.to
don't propagate errors to the parent date
object. Using superRefine
ensures validation applies to the entire object.
Can I use SCSS instead of CSS with Shadcn?
Yes, but ensure the global CSS includes Tailwind directives, as Shadcn heavily relies on Tailwind styles.
What if the selected value resets after submission?
Ensure defaultValues
are properly set in useForm
and the form state is preserved.
Conclusion
By following this guide, you can effectively use the Shadcn/UI Range Date Picker inside a React Hook Form with proper validation and error handling. This ensures a smooth user experience while maintaining clean and maintainable code.