React onBlur is not triggered when choosing date

6.6k views Asked by At

I use jQuery datetimepicker addon in React to create a date-time picker, like the example

Now, I want to implement the validation in onBlur() event to check if the start date > end date or not.

I've implemented it. It will reset the end time as start time the same if start time > end time.

However, it only works by key in. If I choose date from jquery UI, the onBlur() event won't be triggered.

Can somebody tell me what the problem is? Thank you.

<div id={id}>
    <span className='from'>
        <input
            type='text' id={id+'-from'}
            ref='dateFrom'
            onChange={this.handleChange}
            onBlur={this.handleBlur}
            value={value.from} />
    </span>
    <span className='to'>
        <input
            type='text' id={id+'-to'}
            ref='dateTo'
            onChange={this.handleChange}
            onBlur={this.handleBlur}
            value={value.to} />
    </span>
</div>


getInitialState() {
    let prevFrom = ''
    let prevTo = ''

    prevFrom = '2016-12-12'
    prevTo = '2016-12-19'

    return {
        prevFrom,
        prevTo
    }
},
handleChange(evt) {
    let {onChange} = this.props

    let isValidFrom = this.isDateValid(this.dateFrom.value)
    let isValidTo = this.isDateValid(this.dateTo.value)

    if (!isValidFrom) {
        let errMsg = this.handleErrMsg()
        showError(errMsg);
    }

    if (!isValidTo) {
        let errMsg = this.handleErrMsg()
        showError(errMsg);
    }

    onChange({from:this.dateFrom.value, to:this.dateTo.value})
},
handleBlur() {
    let {onChange} = this.props
    let dateFrom = this.dateFrom.value
    let dateTo = this.dateTo.value

    let isValidFrom = this.isDateValid(dateFrom)
    let isValidTo = this.isDateValid(dateTo)
    let isAfter = false

    // Validate the date-time when leave the input
    // If not valid, reset to the previous valid value
    if (!isValidFrom) {
        dateFrom = this.state.prevFrom
        this.dateFrom.value = dateFrom
    }

    if (!isValidTo) {
        dateTo = this.state.prevTo
        this.dateTo.value = dateTo
    }

    // validating the start time > end time
    isAfter = Moment(dateFrom).isAfter(dateTo)

    // Determine the start time is after end time or not;
    // if so, change start time & end time the same
    if (isAfter && isValidFrom) {
        onChange({from:dateFrom, to:dateFrom})
        this.setState({
            prevFrom: dateFrom,
            prevTo: dateFrom
        })
    }
    else if (!isAfter && isValidFrom && isValidTo) {
        onChange({from:dateFrom, to:dateTo})
        this.setState({
            prevFrom: dateFrom,
            prevTo: dateTo
        })
    }
    else {
        onChange({from:this.state.prevFrom, to:this.state.prevTo})
    }
}
2

There are 2 answers

0
Jayssen On BEST ANSWER

After testing the date-time picker on the example page you provided, I noticed the input lost focus as soon as I changed the time with the time picker. That's probably why the onBlur event isn't fired. Instead, you could try providing an onClose event to your date-time picker.

$('#my-datetimepicker').datetimepicker({
    onClose: function(dateText, inst) {
        console.log('validate here');
    }
});
0
Artem Dudkin On

Cannot reproduce error, as this code works

<div id='root'></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.js"></script>

<link rel="stylesheet" href="http://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="http://code.jquery.com/jquery-1.12.4.js"></script>
<script src="http://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>

<script type="text/babel">
    var HelloMessage = React.createClass({
        componentDidMount:function(){
            $("#datepicker").datepicker();
        },
        onBlur: function(){
            console.log("a");
        },
        render: function () {
            return <input type="text" id="datepicker" onBlur={this.onBlur}/>
        }
    });
    ReactDOM.render(<HelloMessage/>, document.getElementById('root'));
</script>