Guide for integrating the shadcn/ui Range Date Picker within a Form

Encountering an issue with using The Range Date Picker within the Form component. Specifically, I am looking to store {from, to} values of the range in an object, however, utilizing an object as a Form field value results in error messages not functioning properly; instead, I receive undefined as an error message.

To resolve this, I have made modifications to the Form Message Component to display errors in a slightly altered format, although I believe this is more of a workaround rather than the correct method.

The code snippet below illustrates the current setup:

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(error) {
    console.log(error);
    /*
    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>
            [...]
          </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>
  );
}

An image showing that the error message appears correctly for the title but shows as undefined for the date can be viewed here: https://i.stack.imgur.com/uo365.png

Answer №1

To set a custom error message, define it like this:

  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(),
  }).refine(
      (data) => data.from > addDays(new Date(), -1),
      "Start date must be in the future"
    ),
});

Make sure to remove date: {} from DefaultValues to avoid undefined issues.

Update the code as follows:

function NewEventPage() {
  const form = useForm({
    resolver: zodResolver(formSchema),
    defaultValues: {
      title: "",
    },

Answer №2

My approach to solving this issue was as follows:

const DATE_REQUIRED_ERROR = "Date must be entered.";

const formSchema = z.object({
   date: z.object({
       from: z.date().optional(),
       to: z.date().optional(),
   }, {required_error: DATE_REQUIRED_ERROR}).refine((date) => {
       return !!date.from;
   }, DATE_REQUIRED_ERROR),
   comment: z.string().min(1, {message: "Please enter a comment."}),
});

The setup may not be elegant, but it resolved the problem I encountered:

  • Upon clicking submit without selecting dates in the range picker, an error message displayed "undefined" due to the detection of undefined date.from, triggering the error for the entire date object but not propagating it up correctly. To address this, I made date.from optional to prevent this error.
  • I then utilized refine((date) => {...}) on the date object itself. This logic checks if date.from is undefined and displays the defined DATE_REQUIRED_ERROR text in the UI. By employing this method, I effectively elevated the error from date.from to the date object for correct display.

But why include

{required_error: DATE_REQUIRED_ERROR}
?

This addition serves a specific purpose:

  • If you initially select dates in the range picker and subsequently remove them, an unexpected Required error might trigger on the date object. Setting the required_error ensures consistency by displaying the same error message ("Date is required") regardless of whether a value was never selected or previously deleted.

In my case, default values were provided through useForm, although they can be omitted without issues.

 const form = useForm<z.infer<typeof formSchema>>({
    resolver: zodResolver(formSchema),
    defaultValues: {
        date: {
            from: undefined,
            to: undefined,
        },
        comment: ''
    },
}); 

Note that the selected field in the Calendar tag requires adjustment due to the optional nature of date.from. Including the ! operator guarantees its definite assignment.

<Calendar
  initialFocus
  mode="range"
  defaultMonth={field.value.from}
  selected={{from: field.value.from!, to: field.value.to}}
  onSelect={field.onChange}
  numberOfMonths={1}
/>

The above code snippet includes all necessary functionality. Keep in mind that the comment field remains unimplemented in the UI with a placeholder value in the defaults:

(Additional code components would be inserted here)

Answer №3

My solution involved the following approach:

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().optional(),
        },
        { required_error: "Date is required." },
      )
      .refine((date) => {
        return !!date.to
      }, "End Date is required."),
});

function NewEventPage() {
  const form = useForm({
    resolver: zodResolver(formSchema),
    defaultValues: {
      title: "",
    },
  });

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to retrieve data in my client component without risking exposing my API key to unauthorized users?

To retrieve information, I plan to use pagination in order to specify a particular page number within the API URL and fetch additional data by updating the value of page. The process of fetching data in my server component is as follows: // fetchData.tsx ...

React/Redux - Issue with rest operator functionality in component

Here is the initial state I am working with: const initialState = { selectedGroup: {}, groups: { rows: [], total: null }, offset: 0, range: 15, loading: false, error: null } Within a reducer function, I have this case for successful ...

Navigate the array and divide the elements into separate values

For a project I need to upload files, wherein the data is organized within an object like [5.76516834507, 50.8474898368], [5.76115833641, 50.8453698247]. The task here is to extract and store the first value as latitude: 5.76516834507 and the second value ...

How can I retrieve the reference number of an item by clicking a button within a list item in an unordered

Presented here is a collection of data points and a button nested within an ul <ul> <li class="mix" category-1="" data-value="600.35" style="display:block;"> <figure> <figcaption> <h3> ...

Issues with npm installation

Having trouble installing 'react-navigation' in my expo (react native) project using the command 'npm install --only=dev react-navigation'. I keep receiving warnings and am unsure how to proceed. See image link for details: enter image ...

How to retrieve an imported tag from an array in React programming

There is an issue with displaying a tag that is imported into an array. {files[1]} seems to be empty. To display the imported tag, I had to resort to using the standard declaration: <FileOne/> This was my attempted solution: const FileOne = ( () ...

Could someone explain to me why searchQuery.value is coming up as undefined?

Within my development task, I am endeavoring to create a functional search icon on the header bar that allows users to input Pokémon names for searching purposes. Despite my efforts, I am consistently facing a console error message suggesting "searchQu ...

The custom validation function in jQuery is not triggering

I am facing an issue with my HTML and JavaScript setup, which looks like this: <html> <head> <title>Validation Test</title> <script src="https://code.jquery.com/jquery-3.4.1.js"></script> <script src="htt ...

Angular JS: Implementing a click event binding once Angular has completed rendering the HTML DOM

Exploring AngularJS for the first time, I've researched extensively but haven't found a satisfying solution. My goal is to retrieve data from the server and bind it to HTML elements on page load. However, I also need to bind click events to these ...

A guide to effectively converting and parsing a class object that includes Uint8Array elements

After stringifying a class object that contains a property in Uint8Array, and then parsing it later, the property is no longer in Uint8Array format. Here's an example: class Example { title:string; byteData:Uint8Array; ...

Error: When attempting to utilize the Image-Slider, an issue arises with reading the property 'classList' which is undefined

I am currently in the process of developing a website using Strapi as my CMS and Next.js(React) for the frontend. The website features an image slider that includes images, headlines, and descriptions. However, I have encountered an issue where after spen ...

How to resolve: Preventing Ajax - Post request from executing repetitively

I am facing an issue with a table that is formatted using the Datatables script. There is a column in the table which contains icons for actions. When a user clicks on an icon, a modal is loaded and its content is fetched using the POST method. The modal ...

Having issues as a Node.js novice with error messages

Here is the code I have for a basic node.js application: var http = require('http'); var fs = require('fs'); var path = require('path'); var url = require('url'); var port = process.env.port || 1337; http.createSer ...

What is the best way to customize the styles of a reusable component in Angular2?

I am working with a reusable component called "two-column-layout-wrapper" that has its styles defined in the main .css file. In another module, I need to use this component but customize the width of two classes. How can I override these styles? import ...

Reducing div size when clicked - Using JQuery version 1.9

I am looking to make a specific div shrink in size, while keeping all the data visible, each time a user clicks on a certain icon with the class legend-icon. For example, I want the div with the ID #Chart to shrink when clicked. This is the HTML code: &l ...

Techniques for implementing a JS script within a useEffect hook in a functional component

I am currently working on a useEffect hook in my project, within which there is an if-else block that includes a Javascript function called 'B1.X.Change' inside the else statement. However, I am facing difficulty binding 'B1.X.Change' t ...

Obtain base64 representation of a file using plupload file uploader

I am currently utilizing the Plupload Uploader. My objective is to convert the uploaded file to base64 and transmit it within a SOAP envelope. I have successfully created the envelope and utilized my web-service. However, I am wondering how I can retrieve ...

``Using backticks to denote HTML syntax - Leveraging Google Charts to create

Has anyone found a way to incorporate HTML in ticks within a Google chart? I am attempting to insert a weather icon from This is my current attempt: const dailyData = new google.visualization.DataTable(); dailyData.addColumn('timeofday' ...

What is the preferred workflow for client-side modules: (Browserify + npm + gulp) or (RequireJS + Bower + gulp)?

As I delve into various client-side Javascript modules workflows for my current Node.JS Express project, I find myself torn between Browserify + npm + gulp and RequireJS + Bower + gulp. While I lean towards CommonJS due to its syntax, the idea of sharing ...

Tips for styling buttons in react-admin with custom CSS

I need some help with customizing buttons in react-admin. I am new to the platform and unsure about how to go about changing the button CSS for various actions such as create, edit, and export. Can anyone provide guidance on the best way to customize these ...