React-datepicker: Datepicker does not open with readOnly=true

Created on 6 Aug 2018  路  9Comments  路  Source: Hacker0x01/react-datepicker

Expected behavior

Datepicker opens, when a user clicks in the input.

Actual behavior

Datepicker does not show up.

Steps to reproduce

  1. Use latest version of Chrome
  2. Navigate to https://reactdatepicker.com/#example-25 > Read only datepicker
  3. Click in the input

Most helpful comment

anyone has an idea on how i could prevent the "soft keyboard" showing on android (and other mobile devices) when clicking on the input field that has the datepicker?

I've ended up building on top of @pniebrzydowski last answer and used a customInput, but modified in such a way that i'm applying the readOnly attribute to the input element conditionally inside the onFocus and onBlur. Whenever onFocus is triggered, i change the state to have readOnly true and whenever onBlur is triggered i change it to false.

class DateOnlyInput extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            readonly: false,
        }
    }

    _onFocus = () => {
        this.setState({
            readonly: true,
        });
    };

    _onBlur = () => {
        this.setState({
            readonly: false,
        });
    };

    render() {
        const props = {...this.props};
        delete props.onBlur;
        delete props.onFocus;
        delete props.readOnly;

        return (
            <input onBlur={this._onBlur} onFocus={this._onFocus} type="text" readOnly={this.state.readonly} {...props} />
        );
    }
}

It seems to get the job done, i'm wondering if there is a better way to go about this tho. seems pretty hacky to me and i'm not sure if there are any potential problems that i might have missed?

All 9 comments

<DatePicker selected={this.state.activitySelectedDate} onChange={this.handleActivityDateChange} includeDates={dates} showDisabledMonthNavigation dateFormat="YYYY-MM-DD" readOnly />

experiencing the same problem here. After updating to 1.6.0 the readOnly attribute seems to be causing the datepicker to not open. There are no errors in console or any other errors, it just does not open.

tried readOnly={true} and readOnly none seem to work.
Removing the attribute makes it work again (but users are able to type into the field then)

looking at some other issues, I found this one:
https://github.com/Hacker0x01/react-datepicker/issues/1418
it seems like that is the reason for the new behaviour.

Solved it by using onKeyDown={e => e.preventDefault()}

did the same thing, and then also needed to add
autoComplete="off"
to prevent chrome from showing the previously selected options

@kevcodez Unfortunately disabling keydown is problematic, as it removes all access to the keyboard which completely eliminates accessibility for the form. You can no longer tab away from the field, you can't use the keyboard to select the date, etc.

My solution was to utilize the customInput property and create a new component which returns an input with the properties passed through, where the onChange is only fired if it matches as a moment object.

Code for the component:

import React from 'react';
import PropTypes from 'prop-types';
import moment from 'moment';

class DateOnlyInput extends React.Component {
    constructor(props) {
        super(props);
        this.checkIfDate = this.checkIfDate.bind(this);
    }

    checkIfDate(date) {
        if (!moment.isMoment(date)) return;
        this.props.onChange(date);
    }

    render() {
        const props = {...this.props};
        delete props.onChange;
        return (
            <input type="text" onChange={this.checkIfDate} {...props} />
        );
    }
}

DateOnlyInput.propTypes = {
    onChange: PropTypes.func,
};

export default DateOnlyInput;

Then I just input this into the customInput in my DatePicker component, and the component works properly again.

<DatePicker
    ...
    customInput={<DateOnlyInput />}
/>

I still see this as a bit of a hack and a bunch of additional unnecessary code, and that this is exactly how it should function (and has in the past) when readOnly is true, but at least it seems to function as needed, and all keyboard functionality is retained. Hopefully the previous "fix" for read-only will be reverted.

anyone has an idea on how i could prevent the "soft keyboard" showing on android (and other mobile devices) when clicking on the input field that has the datepicker?

I've ended up building on top of @pniebrzydowski last answer and used a customInput, but modified in such a way that i'm applying the readOnly attribute to the input element conditionally inside the onFocus and onBlur. Whenever onFocus is triggered, i change the state to have readOnly true and whenever onBlur is triggered i change it to false.

class DateOnlyInput extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            readonly: false,
        }
    }

    _onFocus = () => {
        this.setState({
            readonly: true,
        });
    };

    _onBlur = () => {
        this.setState({
            readonly: false,
        });
    };

    render() {
        const props = {...this.props};
        delete props.onBlur;
        delete props.onFocus;
        delete props.readOnly;

        return (
            <input onBlur={this._onBlur} onFocus={this._onFocus} type="text" readOnly={this.state.readonly} {...props} />
        );
    }
}

It seems to get the job done, i'm wondering if there is a better way to go about this tho. seems pretty hacky to me and i'm not sure if there are any potential problems that i might have missed?

Try this. works for me

const CustomInput = (props) => {
    return (
        <input
            className={[classes.TransparentInput, "uk-input"].join(" ")}
            onClick={props.onClick}
            value={props.value}
            type="text"
            readOnly={true}
        />
    )
}
<DatePicker
  customInput={<CustomInput />}
  name={'from'}
  value={values['from']}
  onChange={e => setFieldValue('from', moment(e).format('L'))}
 />

The setFieldValue is from formik. you can choose not to use formik. Your choice.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jjjss94 picture jjjss94  路  3Comments

rsouthpaw picture rsouthpaw  路  3Comments

pinturic picture pinturic  路  3Comments

sarav1234 picture sarav1234  路  3Comments

ali-master picture ali-master  路  3Comments