hypeserver / react-date-range

A React component for choosing dates and date ranges.
MIT License
2.59k stars 672 forks source link

Open/Close DateRangePicker #364

Closed TerrySlack closed 4 years ago

TerrySlack commented 4 years ago

Subject of the issue

How do you open/close a date range either when you click on the input boxes, the user hits esc, or when the user clicks elsewhere, outside of the calendar?

[BUG] Bug Reproduce Steps

Not a Bug, a question

[BUG] Expected behaviour

Calendar is initially hidden, the user clicks on the input boxes and it opens.. Calendar is closed when the user clicks elsewhere, or hits esc

firzok commented 4 years ago

I think this is a really good idea, I was looking for this behavior but couldn't find it anywhere. I hope someone is working on this. Edit: I think I should do it.

nerycordova commented 4 years ago

Hi @TerrySlack , you can embed it into another component and control its rendering from there, using state:

const DateRangeInput = () => {

  const [open, setOpen] = React.useState(false);

  return (
    <>
      <button onClick={ () => { setOpen(!open); } }>{!open?'Open':'Close'}</button> 
      <br/>
      {open 
        ?<DateRangePicker
            onChange={ (event) => { console.log(event) }}
            ranges={[{selection:{}}]}
            direction="horizontal"
        />
        :''
      }
    </>
  )
}

See an example here.

Dakkers commented 4 years ago

if you want the datepicker to disappear when you click outside of the element, you can do something like this:


class DaterangePicker extends React.Component {
  containerRef = React.createRef();

  render () {
    const now = moment();

    return (
      <div ref={this.containerRef}>
        <DateRangePicker
          onChange={this.onChange}
          ranges={[{
            endDate: this.props.endDate,
            key: 'selection',
            selectedRange: this.props.selectedRange,
            startDate: this.props.startDate
          }]}
        />
      </div>
    );
  }

  componentDidMount () {
    document.body.addEventListener('click', this.onClickOnPage, true);
  }

  componentWillUnmount () {
    document.body.removeEventListener('click', this.onClickOnPage, true);
  }

  onClickOnPage (e) {
    if (!this.containerRef || !this.containerRef.current) {
      return;
    }

    let didClickInside = false;

    let parentElement = e.target;
    while (parentElement) {
      if (parentElement === this.containerRef.current) {
        didClickInside = true;
        break;
      }

      parentElement = parentElement.parentElement;
    }

    if (didClickInside) {
      return;
    }

    // Clicked outside of the date range picker - cancel selection
    this.props.cancel();
  }

  onChange ({ selection }) {
    const startDate = moment(selection.startDate);
    const endDate = moment(selection.endDate);

    this.selectedRange = selection.value || null;
    this.endDate = endDate.toDate();
    this.startDate = startDate.toDate();

    if (!moment(this.startDate).isSame(moment(this.endDate))) {
      this.props.onChange(startDate, endDate);
    }
  }
}