Published on

How to use shadcn/ui Range Date Picker inside Form?

Authors
  • Name
    Ripal & Zalak
    Twitter

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

  1. Validation Errors: Using objects as form field values can lead to issues where error messages are undefined.
  2. State Management: Maintaining the selected range without resetting values can be tricky.
  3. Error Display: Errors may not propagate correctly from nested fields like date.from or date.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.