gene b.
gene b.

Reputation: 11984

React-Datepicker with Formik and Yup: Date value not validated on first blur, other than .required()

I'm using React-Datepicker inside a Formik form validated with Yup. To integrate React-Datepicker inside Formik I used the wrapper solution in this thread.

When a value is initially entered, .required() gets checked, but any other validation does not get checked. So I'm not getting my StartDate later than today validation right away. These other validations do get triggered if I re-enter the control a second time and exit it. So the only initial validation error that happens immediately is .required(), but for any other errors I need to re-touch the control. Are there any solutions to this?

EDIT: I noticed that Formik's .touched does not get set on the 1st DatePicker input. It only gets set on subsequent touches/inputs.

Yup

startDate: yup.date().nullable().required('Start Date is required')
                                .min(new Date(), 'Start Date must be later than today'),

DatePicker Wrapper -see this thread - credit to ToolmakerStever

I tried adding onCalendarClose to force re-validation per this DatePicker issue report, and it indeed may be happening, but this could also be a Yup Schema issue -- I'm not sure.

const { setFieldValue, validateField, values, handleBlur } = useFormikContext();

   return (
        <DatePicker
            {...field} 
            {...props} 
            showMonthDropdown
            showYearDropdown            
            selected={(field.value && new Date(field.value)) || null}
            onChange={val => {
                setFieldValue(field.name, val);
            }}
            onCalendarClose={val => {
                // Force-validate onCalendarClose to avoid any potential DatePicker Blur issues
                // Didn't help
                validateField(props.name);
            }} 
            onBlur={e => {
                // Call Formik's handleBlur
                // Didn't help
                handleBlur(e);
            }}           
          
        />

    )

Upvotes: 3

Views: 14636

Answers (3)

zhuhang.jasper
zhuhang.jasper

Reputation: 4465

For those using react-hook-form with yup, trigger onBlur inside onChange

<Controller
 name='dateOfBirth'
 control={control}
 render={({ field: { name, value, onChange, onBlur } }) => (
  <DatePicker
      selected={value}
      preventOpenOnFocus={true}
      maxDate={new Date()}
      dateFormat="yyyy-MM-dd"
      placeholderText='YYYY-MM-DD'
      onBlur={onBlur}
      onChange={(date: Date) => {
        onChange(date);
        onBlur();
      }}
      customInput={<DatePickerInput/>}
    />

Upvotes: 1

gene b.
gene b.

Reputation: 11984

I found a fix. Something wasn't marking the DatePicker as touched the first time. DatePicker exposes an event called onChangeRaw where I force-touched the control. Now all errors are triggered right away without re-touching.

        onChangeRaw={e => {
            setFieldTouched(field.name, true, true);
        }}

This goes inside the DatePicker Wrapper for Formik, as shown in this post.

React-Datepicker has a bug with Blur for some reason, documented here. Their Blur recommendations include calling onCalendarClose or onChangeRaw. But only onChangeRaw worked reliably for me.

Upvotes: 4

Shyam
Shyam

Reputation: 5497

Creating a wrapper with Field works fine . The validations are getting triggered without any issues. Here is the sandbox.

Formik DatePicker Example

Upvotes: 1

Related Questions