Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Date Range with single DatePicker #584

Closed
hoodsy opened this issue Oct 11, 2016 · 21 comments
Closed

Date Range with single DatePicker #584

hoodsy opened this issue Oct 11, 2016 · 21 comments

Comments

@hoodsy
Copy link

hoodsy commented Oct 11, 2016

Is this at all possible? The example for date range is exactly the functionality I would want, but it would be best if the user is selecting the range on a single calendar, not through 2 separate inputs.

@rafeememon
Copy link
Contributor

Yep, it's possible -- you'll need to define your own way of setting startDate and endDate based on onChange events.

@hoodsy
Copy link
Author

hoodsy commented Oct 11, 2016

@rafeememon sweet! thanks for the quick response. How about the hover styling, to show the range. It seems like that is controlled by selectsStart and selectsEnd

@rafeememon
Copy link
Contributor

Check out the example on the demo page

@rafeememon
Copy link
Contributor

Actually, I don't think we currently support having selectsStart and selectsEnd on the same picker. Not sure how the semantics of this would work, but PRs to support this are welcome.

@rafeememon rafeememon reopened this Oct 11, 2016
@sahanarula
Copy link

Looking forward for the best solution.

@TrejGun
Copy link

TrejGun commented Dec 7, 2016

would love to see this feature too

@martijnrusschen
Copy link
Member

I agree, would love to see if someone could diff up a PR.

@TrejGun
Copy link

TrejGun commented Dec 24, 2016

probably its better to use https://github.com/airbnb/react-dates :)

@Charlie91
Copy link

Ok, it's possible through the setting startDate and endDate, but how can I display two dates at one input field? It seems that I can only display one date at one time

@marinarjumina
Copy link

marinarjumina commented May 13, 2019

May be it helps someone in the future:

Get weekStartDay and weekEndDay:

const weekStartDay = startOfWeek(currentDate, { weekStartsOn: 1 })
const weekEndDay = endOfWeek(currentDate, { weekStartsOn: 1 })

Prepare inputValue range dates output:

const inputValue = format(weekStartDay, "dd/MM/yyyy") + ' - ' + format(weekEndDay, "dd/MM/yyyy")

Pass formatted inputValue to Datepicker's value:

<DatePicker selected={weekStartDay} highlightDates={highlightDates} onChange={setCurrentDate} locale="enGB" value={inputValue} />

For me it works.

@vedadeepta
Copy link

vedadeepta commented Jun 18, 2019

Recently came across this use-case. This can be implemented as follows:


  handleChange = date => {
    const { format } = this.props
    if (date) {
      if (!this.state.date) {
        return this.setState({ date })
      }
      this.setState({
        endDate: date,
        rangeDate: `${this.state.date.format(format)} -> ${date.format(format)}`
      })
      return this.props.onDateChange(
        this.state.date.format(format),
        date.format(format)
      )
    }
    this.props.onDateChange(null)
  }

  render () {
        return <DatePicker
          selected={date}
          dateFormat={format}
          onChange={this.handleChange}
          selectsEnd: Boolean(date),
          minDate: date,
          startDate: date,
          endDate: endDate,
          shouldCloseOnSelect: Boolean(date),
          customInput: <div>{this.state.rangeDate || 'Select Date Range'}</div>
        />
  }

@DeanHand
Copy link

DeanHand commented Sep 4, 2019

Thanks @vedadeepta for the starting point. This method works perfectly for what I need. Hopefully will help anyone else looking for this. You may want to add additional checks to stop the start date being selected after the end date and vice versa.

There's also a workaround for when selecting the same day for start and end date, onChange doesn't fire so I'm leveraging onSelect instead. If anyone knows a better solution for this please add it!

  const [startDate, setStartDate] = useState(undefined);
  const [endDate, setEndDate] = useState(undefined);
  const [selectionComplete, toggleSelectionComplete] = useState(false);

  const handleDateChange = date => {
    if (!selectionComplete && !startDate) {
      //on first date selection, set the start date

      setStartDate(date);
      return;
    }

    if (!selectionComplete && startDate && !endDate) {
      //on second date selection, set the end date

      setEndDate(date);
      toggleSelectionComplete(true);

      //do stuff with date range

      return;
    }

    if (selectionComplete && startDate && endDate) {
      //on third date selection, begin selection of a new date range
      //reset the start date and clear the end date.

      setStartDate(date);
      setEndDate(undefined);
      toggleSelectionComplete(false);
      return;
    }
  };

  const handleSelect = date => {
    //onChange is not fired if selecting same date - workaround to fire handleDateChange
    if (!selectionComplete && startDate && !endDate && sameDay(date, startDate)) {
      handleDateChange(date);
    }
  };

  const sameDay = (d1, d2) => {
    return d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth() && d1.getDate() === d2.getDate();
  };

  return (
    <DatePicker 
      selected={startDate} 
      onChange={handleDateChange} 
      onSelect={handleSelect}
      selectsEnd={Boolean(startDate)} 
      startDate={startDate} 
      endDate={endDate} 
      inline
    >
      <div className="date-range">
        {startDate ? moment(startDate).format('DD/MM/YYYY') : '??/??/????'} - {endDate ? moment(endDate).format('DD/MM/YYYY') : '??/??/????'}
      </div>
    </DatePicker>
  );

@stale
Copy link

stale bot commented Mar 2, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Mar 2, 2020
@rs-8
Copy link

rs-8 commented Mar 12, 2020

Seems like need pull request to enable this feature (selectRange props maybe)

@stale stale bot removed the wontfix label Mar 12, 2020
@tdiluzio
Copy link

Thanks @DeanHand for your demo 👍 Here's my two cents: a simple range demo, I've pasted only useful stuffs. Hope it'll help someone out there:

export function DemoDatePicker() {
  // range demo
  const [startDate, setStartDate] = useState(null);
  const [endDate, setEndDate] = useState(null);

  function handleDateChange(date) {
    // initial change start by setting the startDate
    if (!startDate && !endDate) {
      setStartDate(date);
      // startDate has been set, set the end date
    } else if (startDate && !endDate) {
      setEndDate(date);
    }

    // user is choosing another range => set the start date
    // and set the endDate back to null
    if (startDate && endDate) {
      setStartDate(date);
      setEndDate(null);
    }
  }

  return (
    <div>
      <DatePicker
        onChange={(date) => handleDateChange(date)}
        selectsStart={true}
        selected={startDate}
        startDate={startDate}
        endDate={endDate}
        inline={true}
      />
    </div>
  );
}

martijnrusschen pushed a commit that referenced this issue Jul 9, 2020
* add logic for getting date range
* transfer prop for it through parents components to children
* add logic for getting styles for range

* add tests for selectsRange prop

* add example of using selectsRange prop to docs-site

* refactoring
* remove extra code
* add tests
* add condition check for set same date when selectsRange

* refactore and correct test
@jesslombera
Copy link

jesslombera commented Sep 1, 2020

I wanted to show 2 month calendar on openToDate to select two dates with date range functionality and show the dates selected on the input field.

Here is what I did with 2 months shown for Date Range: has the openToDate attribute, has placeholderText ("Select custom date"), moment to format, and I set the value with the custom inputValue that holds startDate and endDate:

This worked for what I wanted to accomplish. I hope it helps.

  const [endDate, setEndDate] = useState(null);
  const onChange = (dates) => {
    const [start, end] = dates;
    setStartDate(start);
    setEndDate(end);
  };
  const inputValue =
    moment(`${startDate}`).format('MM/DD/YYYY') +
    ' - ' +
    moment(`${endDate}`).format('MM/DD/YYYY');

  return (
    <DatePicker
      selected={null}
      onChange={onChange}
      placeholderText="Select Custom date"
      startDate={startDate}
      endDate={endDate}
      selectsRange
      monthsShown={2}
      openToDate={new Date()}
      value={!endDate ? new Date() : inputValue}
    />
  );

@dextermb
Copy link

dextermb commented Jan 5, 2021

The issue I am having with the selectsRange prop without inline is that the calendar closes after selecting the start date, meaning users have to reopen the calendar to select the end date.

What's the best method for keeping the calendar open until an end date is selected? Is it even possible?

Edit: Having a poke around there seems to be a setOpen method, but this does not seem to keep the calendar open

onChange={([startDate, endDate]) => {
  setStartDate(startDate)
  setEndDate(endDate)

  if (endDate === null) {
    calendar?.current.setOpen(true, true)
  }
}}

Edit: Seems like using useEffect on the endDate might be a valid solution, although not ideal

React.useEffect(() => {
  if (!endDate) {
    calendar?.current.setOpen(true, true)
  }
}, [endDate])

@josias-r
Copy link

Yup, came across the same problem as @dextermb. It took me a while until I noticed that inline is the culprit. They also have it in the docs.

This is a bug, right? Otherwise, it should be mentioned in the docs that inline is required for some reason to work with selectsDate

@kellydena-TTMSTech
Copy link

kellydena-TTMSTech commented Feb 9, 2021

suggest using shouldCloseOnSelect to solve this problem @josias-r

@khuongphp
Copy link

khuongphp commented Jan 13, 2022

suggest using shouldCloseOnSelect to solve this problem @josias-r

Thank you. That should be the right answer. But seem complex :D :D
There are some difference with the document
https://reactdatepicker.com/#example-date-range-using-input-with-clear-button

@khuongphp
Copy link

update to verson "react-datepicker": "^4.6.0" resolved my issue

p-rogas pushed a commit to p-rogas/react-datepicker that referenced this issue Mar 22, 2023
* add logic for getting date range
* transfer prop for it through parents components to children
* add logic for getting styles for range

* add tests for selectsRange prop

* add example of using selectsRange prop to docs-site

* refactoring
* remove extra code
* add tests
* add condition check for set same date when selectsRange

* refactore and correct test
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests