onChange (single mode)

The difference between onChange in this package and others is that type of its argument is sent as DateObject instead of Date.

You can easily convert it to Date with the toDate() method.

import { useState } from "react"
import DatePicker from "react-multi-date-picker"

export default function Example() {
  const [value, setValue] = useState()
  
  return (
    <>
      <DatePicker
        value={value}
        onChange={setValue}
      />
      {value?.toDate?.().toString()}
    </>
  )
}

onChange (Converting Selected Date To All Calendars)

//gregorian calendar & locale
import gregorian from "react-date-object/calendars/gregorian";
import gregorian_en from "react-date-object/locales/gregorian_en";

//persian calendar & locale
import persian from "react-date-object/calendars/persian";
import persian_en from "react-date-object/locales/persian_en";

//arabic calendar & locale
import arabic from "react-date-object/calendars/arabic";
import arabic_en from "react-date-object/locales/arabic_en";

//indian calendar & locale
import indian from "react-date-object/calendars/indian";
import indian_en from "react-date-object/locales/indian_en";
.
.
.
const [state, setState] = useState({ format: "MM/DD/YYYY" })
  
const convert = (date, format = state.format) => {
  let object = { date, format }
  
  setState({
    gregorian: new DateObject(object).format(),
    persian: new DateObject(object).convert(persian, persian_en).format(),
    arabic: new DateObject(object).convert(arabic, arabic_en).format(),
    indian: new DateObject(object).convert(indian, indian_en).format(),
    jsDate: date.toDate(),
    ...object
  })
}
  
const Span = ({ children }) => <span style={{ fontWeight: "bold" }}>{children}</span>

return(
  <div>
    <div>
      <div>
        <Span>click to select: </Span>
        <DatePicker
          value={state.date}
          onChange={convert}
        />
      </div>
      <div>
        <Span>format: </Span>
        <select
          value={state.format}
          onChange={e => convert(state.date, e.target.value)}
          className="select"
        >
          <option>MM/DD/YYYY</option>
          <option>DD-MM-YYYY</option>
          <option>YYYY,MM,DD</option>
          <option>dddd DD MMMM YYYY</option>
          <option>ddd MMM DD YYYY HH:mm:ss</option>
          <option>MMM/DD/YYYY hh:mm:ss a</option>
          <option>MMM/DD/YYYY HH:mm:ss</option>
        </select>
      </div>
      <div>
        <Span>gregorian: </Span>
        <span>{state.gregorian}</span>
      </div>
      <div>
        <Span>solar hijri: </Span>
        <span>{state.persian}</span>
      </div>
      <div>
        <Span>islamic hijri: </Span>
        <span>{state.arabic}</span>
      </div>
      <div>
        <Span>indian: </Span>
        <span>{state.indian}</span>
      </div>
      <div>
        <Span>javascript date: </Span>
        <span>{state.jsDate?.toString?.()}</span>
      </div>
    </div>
  </div>
)
click to select:
format:
gregorian:
solar hijri:
islamic hijri:
indian:
javascript date:

onChange (multiple mode)

<DatePicker
  multiple
  onChange={array => { //Array of Dateobjecs
    alert("selected dates :\n" + array.join(",\n"))
  }}
/>

OnOpen

If you have a specific condition for opening or closing the calendar, you can use onOpen and onClose events.

If you return false in onOpen, the calendar will not open. Also, if you return false in onClose, the calendar will not close.

const [shouldOpenCalendar, setShouldOpenCalendar] = useState(false)
.
.
.
<div>
  <DatePicker
    onOpen={() => shouldOpenCalendar}
  />
  <label>
    <input
      type="checkbox"
      checked={shouldOpenCalendar}
      onChange={() => setShouldOpenCalendar(!shouldOpenCalendar)}
    />
    Should open calendar
  </label>
</div>

OnClose

const [shouldCloseCalendar, setShouldCloseCalendar] = useState(false)
.
.
.
<div>
  <DatePicker
    onClose={() => shouldCloseCalendar}
  />
  <label>
    <input
      type="checkbox"
      checked={shouldCloseCalendar}
      onChange={() => setShouldCloseCalendar(!shouldCloseCalendar)}
    />
    Should close calendar
  </label>
</div>

onPositionChange

Each time the popper(calendar) position is recalculated, the onChange function is executed in the element-popper.

Because onChange does something else in datepicker, I changed its name to onPositionChange here.

The function you enter in onPositionChange is executed when scrolling, resizing, opening the calendar, or when you call refreshPosition from datepicker ref.

In the onPositionChange function, an object is sent as an argument containing the calculated popper(calendar) and arrow positions, as well as scrollable date picker parent elements.

In this example, the mentioned object is logged in the console and you can view it by opening your browser console (Ctrl + Shift + i, in Chrome browser).

<DatePicker
  onPositionChange={data => console.log(data)}
/>

onPropsChange

This feature is suitable for plugins.

Because for some of them, setting the DatePicker props (parent component) from the plugins (child component) is inevitable.

const [props, setProps] = useState({ 
  value: new Date(),
  format: "MM-DD-YYYY",
  onChange: (date) => console.log(date.format()),
});
.
.
.
<DatePicker 
  {...props} 
  onPropsChange={setProps} 
/> 

onMonthChange

In this example, setting the currentDate property is optional.

The currentDate property is set to open the calendar in the same selected month.

import React, { useState } from "react";
import DatePicker, { DateObject } from "react-multi-date-picker";

export default function Example() {
  const [dateObject, setDateObject] = useState(
    new DateObject()
  );

  return (
    <>
      <DatePicker
        onMonthChange={(date) => setDateObject(new DateObject(date))}
        onChange={(date) => setDateObject(new DateObject(date))}
        currentDate={dateObject}
      />
      <p>Selected Month: {dateObject.month.name}</p>
    </>
  )
}

Selected Month: October

onYearChange

like the onMonthChange, a date with the type of DateObject is sent as an argument in onYearChange function.

For example you can use the onYearChange and onMonthChange Props, if you want to implement a DatePicker in which the month and year of the user-selected date changes by changing the month and year of the calendar.

import React, { useState } from "react";
import DatePicker, { DateObject } from "react-multi-date-picker";

export default function Example() {
  const [value, setValue] = useState();

  return (
    <DatePicker
      value={value}
      onChange={setValue}
      onYearChange={updateValue}
      onMonthChange={updateValue}
    />
  )

  function updateValue({ year, month }) {
    setValue(
      new DateObject(value).set({
        day: value.day > month.length ? month.length : value.day,
        month,
        year,
      })
    );
  }
}

onFocusedDateChange

The onFocusedDateChange property receives a function and calls it with two arguments (the first argument is dateFocused, and the second argument is dateClicked), which can be called by the Calendar itself or any of the plugins.

The difference between when onFocusedDateChange is called by the Calendar itself and when it is called by one of the plugins is that in the first case the second argument (ie dateClicked) is always present, and in the second case the second argument is always undefined.

The onFocusedDateChange property actually specifies two things.

  1. Which date is currently focused.

  2. Which date is currently clicked.

The nature of the two is different from each other and is sent as two arguments to the listener you have specified.

There are a few things to keep in mind about this property.

  • Both of these arguments may have the same type (either DateObject or undefined)

  • One of them may be DateObject and the other may be undefined.

Here I will describe the different conditions:

  • Single & Range Modes:

    • Both arguments have the same type (DateObject).

    • This means that the date focused is the same as the date clicked.

  • Multiple Mode:

    • As long as the user is selecting new dates, both arguments have the same type (DateObject).

    • This means that the date focused is the same as the date clicked.

    • But as soon as the user clicks on the date that already selected, The selected date is deleted and one of the following cases may occur:

      • the date that is deleted is the same as the focused date, in which case the first argument (ie dateFocused) is undefined and the second argument (ie dateClicked) is the clicked date.

      • the deleted date is not the same as the focused date, in which case the first argument is the previous focused date, and the second argument is the current deleted date.

  • DatePanel:

    • As a plugin, the second argument is always undefined.

    • Clicking on any dates displayed on the DatePanel, will focus that date, so if you click on any date of DatePanel, the first argument (ie dateFocused) will be the same as the clicked date.

    • If the user deletes an unfocused date through the dates panel, the first argument is the same as the previous focused date.

    • If the user deletes a focused date through the dates panel, the first argument is also undefined.

import React, { useState } from "react";
import DatePicker from "react-multi-date-picker";
import DatePanel from "react-multi-date-picker/plugins/date_panel";
.
.
.
const [state, setState] = useState({});
.
.
.
<>
  <DatePicker
    multiple
    onFocusedDateChange={(dateFocused, dateClicked) => {
      setState({ dateFocused, dateClicked });
    }}
    onClose={() => setState({})}
    plugins={[<DatePanel markFocused />]}
    
  />
  <div>
    <p>
      <b>Date focused:</b> {state.dateFocused?.format?.()}
    </p>
    <p>
      <b>Date clicked:</b> {state.dateClicked?.format?.()}
    </p>
  </div>
</> 

Date focused:

Date clicked:

See Also:

DatePanel #customizing-focused-date