Jayant Patil
Jayant Patil

Reputation: 1587

React DatePicker how to open datepicker on click of icon

Trying to open datepicker on click of icon of react-datepicker component, I have gone through their docs and issues links but found that its not much useful.

<DatePicker
        {...startDateOpts}
        id='abc'
        maxDate={moment()}
        onChange={this.handleStartChange}
        placeholderText='Start Date'
        popoverAttachment={smallScreen ? 'bottom center' : undefined}
        popoverTargetAttachment={smallScreen ? 'top center' : undefined}
        popoverTargetOffset={smallScreen ? '0px 0px' : undefined}
      />

enter image description here

I tried from React-datepicker docs link but no luck.

Upvotes: 18

Views: 78733

Answers (11)

Tushar Gautam
Tushar Gautam

Reputation: 1

We can use the prop toggleCalendarOnIconClick to open date picker on click of icon refer the link below [1]: https://reactdatepicker.com/#example-toggle-calendar-open-status-on-click-of-the-calendar-icon

Upvotes: 0

Shivam Jha
Shivam Jha

Reputation: 4482

If you want to do it in functional component:

const startRef = useRef<DatePicker<never, undefined>>(null);

<DatePicker
  ref={startRef}
/>
<button onClick={() => startRef.current?.setOpen(true)}></button>

You want to do it (native JS version)

openDatepicker = (e) => {

    // find date picker input element
    const inputElement = e.target.closest('.my-wrapper-class')?.querySelector('input')

    return inputElement?.click();

  }

Upvotes: 3

Ahmed Raza
Ahmed Raza

Reputation: 19

      const datePickerRef = useRef<ReactDatePicker<never, undefined> | null>();


  <div className="relative">
        <ReactDatePicker
          ref={(pickerRef) => {
            datePickerRef.current = pickerRef;
          }}
          id={id}
          className={datePickerClass({ intent })}
          placeholderText={placeholder}
          selected={value}
          dateFormat={dateFormate}
          showTimeInput={showTimeInput}
          onChange={(date) => {
            if (onChange && date) {
              onChange(date);
            }
          }}
          onBlur={onBlur}
        />
        <CalendarIcon
          className="absolute right-2 top-2.5 z-0 h-5 w-5 text-gray-400"
          onClick={() => {
            if (datePickerRef.current) {
              datePickerRef.current.setOpen(true);
            }
          }}
        />
      </div>

Upvotes: 0

Rahul Gupta
Rahul Gupta

Reputation: 10141

This can be achieved using ref as below:

const datepickerRef = useRef(null); // OR React.createRef();  if you are not using hooks

// OPENS UP THE DATEPICKER WHEN THE CALENDAR ICON IS CLICKED FOR THE INPUT FIELD
function handleClickDatepickerIcon() {
  const datepickerElement = datepickerRef.current;
  // console.log("datepickerElement = ", datepickerElement);
  datepickerElement.setFocus(true);
}

<DatePicker
  {...startDateOpts}
  id="abc"
  maxDate={moment()}
  onChange={this.handleStartChange}
  placeholderText="Start Date"
  popoverAttachment={smallScreen ? "bottom center" : undefined}
  popoverTargetAttachment={smallScreen ? "top center" : undefined}
  popoverTargetOffset={smallScreen ? "0px 0px" : undefined}
  ref={datepickerRef} // attach the ref
/>;

{/* CALENDAR ICON */}
<span className="calender-placment" onClick={() => handleClickDatepickerIcon()}>
  <i className="fal fa-calendar-alt" />
</span>

Upvotes: 3

rajat sharma
rajat sharma

Reputation: 9

The accepted answer is having some issues in that, like -> When user select the date, the calender is not closing on date select, as the <label> trying to setOpen = true again so even after selecting the date, the claendar still open.

How to overcome this issue? see below the simple answer ->

this.state = {
openCalendar : false,
date : new Date()
}

handleChange = date => this.setState({ setDate : date });

      render(){
           return(
               <label>
                   <DatePicker
                      selected={this.state.date}
                      onFocus={() => this.setState({ openCalendar: true })}
                      onChange={this.handleDateChange}
                      open={this.state.openCalendar}
                  />
                 //you can add any icon here and on click that, the date will work as expected.
               <svg/>  //add any icon you want
               </label>
    )
  }

Upvotes: -1

fabio.sang
fabio.sang

Reputation: 905

If you want to programmatically open the datepicker or if you just don't want to use a <label> wrapper you can set a ref to the datepicker component and use setOpen(bool) to open it. Notice that since we're using refs, the component should be stateful.

Example:

openDatepicker = () => this._calendar.setOpen(true);


render() {
    <Datepicker
        {...datepickerProps}
        ref={(c) => this._calendar = c} />

    <img src={iconImg} onClick={this.openDatepicker} />
}

There is currently an open issue on the datepicker's Github stating that this is missing from the docs.

Upvotes: 26

@Jayant Patil I have achieved the functionality of opening react-datepicker on click of an icon.

This is how I did it.

  1. I have created a wrapper component around the date picker and passed an id as props to it.
class DateRangePicker extends React.Component {
    constructor(props, context) {
        super(props, context);
        // DatePicker is a controlled component.
        // This means that you need to provide an input value
        // and an onChange handler that updates this value.
    }
    render() {
        return <DatePicker
            id={this.props.id}
            selected={this.props.selected}
            onChange={this.props.onChange}
            onChangeRaw={this.props.onChangeRaw}
            onBlur={this.props.onBlur}
            peekNextMonth={true}
            showMonthDropdown={true}
            showYearDropdown={true}
            dropdownMode="select"
            placeholderText="MM/DD/YYYY"
            dateFormat="MM/DD/YYYY"
            shouldCloseOnSelect={true}
            defaultValue={null}
            />
    }

}
export default DateRangePicker;
  1. Then enclose your icon using a label and then pass the id.
        <DateRangePicker
            ref={'calendar1'}
            id={'fromdate'}
            dateFormat={gridAttributes.DEFAULT_DATE_FORMAT}
            selected={this.state.fromDate}
            onChange={this.handleDateChange.bind(this, 'fromDate')}
            onChangeRaw={(e) => this.handleRawFromDateChange(e)}
            onBlur={this.handleFromBlur.bind(this)}
            peekNextMonth={true}
            placeholderText={gridAttributes.DEFAULT_DATE_FORMAT}
            showMonthDropdown={true}
            showYearDropdown={true}
            defaultValue={null}
            className="calendar1"
        />
 <label className="icon iconCalendar calendar" style={{ fontSize: '20px' }} htmlFor='fromdate' />

This works without affecting any functionality unlike when only enclosing the icon with label as said by @tre

<label>
<DatePicker/> </label>

causes the calendar to be in open and can be closed only when we click outside the calendar.

Upvotes: 0

tre
tre

Reputation: 915

Just wrap DatePicker with label. All click inside label call focus on input, that open calendar.

<label>
    <DatePicker/>
</label>

Upvotes: 42

Michael Horojanski
Michael Horojanski

Reputation: 4701

I have just finished that by that way,

svg icon has been imported by webpack

    import IconCalendar from 'IconCalendar';

the render function in main component

    render() {
        const {reportSettings: {
                dateTo
            }} = this.props;
        return (
            <div id="date-picker">
                <Label for="date-picker-1">Select Results date</Label>
                <DatePicker todayButton={"Today"} dateFormat={Constants.DATE_FORMAT} customInput={(<ExampleCustomInput/>)} selected={dateTo} onChange={this.handleChange}/>
            </div>
        );
    }

Secondary component that renders input field and icon

class ExampleCustomInput extends Component {
    static propTypes = {
        onClick: PropTypes.func,
        value: PropTypes.string
    }
    render() {
        const {value, onClick} = this.props;

        return (
            <div className="form-group">
                <input type="text" className="form-control" value={value} onClick={onClick}/>
                <IconCalendar className="date-picker-icon" onClick={onClick}></IconCalendar>
            </div>
        );
    }
}

finally css helped me to display icon on input field

.date-picker-icon {
            float: right;
            margin-right: 6px;
            margin-top: -30px;
            position: relative;
            z-index: 2;
        }

Upvotes: 4

BatFace
BatFace

Reputation: 11

Added in version 0.30.0, I think the customInput prop would allow you to do this. That way you could create your own input component and attach the onClick handler to the icon inside it.

Upvotes: 1

Jayant Patil
Jayant Patil

Reputation: 1587

After adding newer version of react-datepicker i.e. 0.30.0 i got props autofocus but, again I got problem that only worked for first time then i tried using ref like below

refs='startDate'

in datepicker then in this object i got

this.refs.startDate.deferFocusInput();

So i called it and I got date-picker open on click of icon

Upvotes: 2

Related Questions