ItzaMi
ItzaMi

Reputation: 367

React-datepicker | Calendar not closing on selection of date

I've seen this issue but it doesn't seem to offer any solution to my problem.

Recently I picked up a project that uses react-datepicker and there's an issue where the calendar just isn't closing on selection of a date. Here's a gif showcasing that

reactdatepicker

My DatePicker component is here

const DatePicker: FC<Props> = ({
  label,
  icon,
  date,
  onChange,
  minDate,
  maxDate,
  selectsStart,
  selectsEnd,
}) => {
  const dateObj = useMemo(() => (date ? date.toDate() : null), [date])
  const minDateObj = useMemo(() => (minDate ? minDate.toDate() : null), [
    minDate,
  ])
  const maxDateObj = useMemo(() => (maxDate ? maxDate.toDate() : null), [
    maxDate,
  ])

  return (
    <div className={css.host}>
      <div className={css.label}>{label}</div>
      <label className={`${css.wrapper}`}>
        {icon}
        <ReactDatePicker
          selected={dateObj}
          className={css.input}
          calendarClassName={css.calendar}
          showTimeSelect
          dateFormat="dd/MM/yyyy h:mm aa"
          onChange={(newDate: Date, e) => {
            if (newDate) {
              const momentDate = moment(newDate)
              onChange(momentDate)
            }
          }}
          startDate={minDateObj}
          endDate={maxDateObj}
          minDate={minDateObj}
          maxDate={maxDateObj}
          selectsStart={selectsStart}
          selectsEnd={selectsEnd}
          showPopperArrow={false}
          popperModifiers={{
            offset: {
              enabled: true,
              offset: '-28px, 4px',
            },
          }}
          renderCustomHeader={customHeader}
        />
      </label>
    </div>
  )
}

And it's being used here

<div
      className={css.host}
      onKeyUp={(evt) => {
        if (evt.keyCode === 13) {
          onSearch({ startDate, endDate, text })
        }
      }}
    >
      <DatePicker
        id="startDate"
        label="Start date"
        icon={<DateStartIcon width={16} height={16} />}
        date={startDate}
        maxDate={endDate}
        onChange={(newDate: Moment) => {
          setStartDate(newDate)
        }}
        selectsStart
      />
</div>

Inside my ReactDatePicker I tried to set the onChange like so

onChange={(newDate: Date, e) => {
    if (newDate) {
        if (e && typeof e.preventDefault === 'function') {
            e.preventDefault();
        }
        const momentDate = moment(newDate)
        onChange(momentDate)
    }
}}

I'm not sure what else I can do here so any help would be great!

Upvotes: 5

Views: 14369

Answers (2)

Mario Perez
Mario Perez

Reputation: 3367

This issue occurs because you are wrapping you datepicker component inside a <label> tag, unwrap the datepicker from it like this:

const DatePicker: FC<Props> = ({
  label,
  icon,
  date,
  onChange,
  minDate,
  maxDate,
  selectsStart,
  selectsEnd,
}) => {
  const dateObj = useMemo(() => (date ? date.toDate() : null), [date])
  const minDateObj = useMemo(() => (minDate ? minDate.toDate() : null), [
    minDate,
  ])
  const maxDateObj = useMemo(() => (maxDate ? maxDate.toDate() : null), [
    maxDate,
  ])

  return (
    <div className={css.host}>
      <div className={css.label}>{label}</div>
      <label className={`${css.wrapper}`}>
        {icon}
      </label>
        
      <ReactDatePicker
        selected={dateObj}
        className={css.input}
        calendarClassName={css.calendar}
        showTimeSelect
        dateFormat="dd/MM/yyyy h:mm aa"
        onChange={(newDate: Date, e) => {
          if (newDate) {
            const momentDate = moment(newDate)
            onChange(momentDate)
          }
        }}
        startDate={minDateObj}
        endDate={maxDateObj}
        minDate={minDateObj}
        maxDate={maxDateObj}
        selectsStart={selectsStart}
        selectsEnd={selectsEnd}
        showPopperArrow={false}
        popperModifiers={{
          offset: {
            enabled: true,
            offset: '-28px, 4px',
          },
        }}
        renderCustomHeader={customHeader}
      />
      
    </div>
  )
}

You'll likely need to redo some CSS

Upvotes: 7

Kamran
Kamran

Reputation: 371

enter image description here
Use shouldCloseOnSelect prop as true to forcefully close after selection

 () => {
      const [startDate, setStartDate] = useState(new Date());
      return (
        <DatePicker
          selected={startDate}
          onChange={date => setStartDate(date)}
          shouldCloseOnSelect={true}
        />
      );
    };

Update You are using showTimeSelect property which awaits selection of time and then upon selection closes it automatically. This is the designed feature of React Datepicker. If you want to just select date and keep the same time and close upon selection of date then you can use another variant from datepicker which is input time.

() => {
  const [startDate, setStartDate] = useState(new Date());
  return (
    <DatePicker
      selected={startDate}
      onChange={date => setStartDate(date)}
      timeInputLabel="Time:"
      dateFormat="MM/dd/yyyy h:mm aa"
      showTimeInput
    />
  );
};

Upvotes: 1

Related Questions