diff --git a/src/index.jsx b/src/index.jsx index 6d9fa11b9..dc55b79f1 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -53,6 +53,7 @@ function hasPreSelectionChanged(date1, date2) { /** * General datepicker component. */ +const INPUT_ERR_1 = "Date input not valid."; export default class DatePicker extends React.Component { static propTypes = { @@ -99,6 +100,7 @@ export default class DatePicker extends React.Component { onKeyDown: PropTypes.func, onMonthChange: PropTypes.func, onYearChange: PropTypes.func, + onInputError: PropTypes.func, openToDate: PropTypes.object, peekNextMonth: PropTypes.bool, placeholderText: PropTypes.string, @@ -162,6 +164,7 @@ export default class DatePicker extends React.Component { onMonthChange() {}, preventOpenOnFocus: false, onYearChange() {}, + onInputError() {}, monthsShown: 1, withPortal: false, shouldCloseOnSelect: true, @@ -248,6 +251,8 @@ export default class DatePicker extends React.Component { : this.calcInitialState().preSelection }); }; + inputOk = () => + isMoment(this.state.preSelection) || isDate(this.state.preSelection); handleFocus = event => { if (!this.state.preventFocus) { @@ -418,18 +423,19 @@ export default class DatePicker extends React.Component { const copy = newDate(this.state.preSelection); if (eventKey === "Enter") { event.preventDefault(); - if ( - isMoment(this.state.preSelection) || - isDate(this.state.preSelection) - ) { + if (this.inputOk()) { this.handleSelect(copy, event); !this.props.shouldCloseOnSelect && this.setPreSelection(copy); } else { this.setOpen(false); + this.props.onInputError({ code: 1, msg: INPUT_ERR_1 }); } } else if (eventKey === "Escape") { event.preventDefault(); this.setOpen(false); + if (!this.inputOk()) { + this.props.onInputError({ code: 1, msg: INPUT_ERR_1 }); + } } else if (eventKey === "Tab") { this.setOpen(false); } else if (!this.props.disabledKeyboardNavigation) { diff --git a/test/datepicker_test.js b/test/datepicker_test.js index d5f43a5d1..7f9b42a2f 100644 --- a/test/datepicker_test.js +++ b/test/datepicker_test.js @@ -460,8 +460,15 @@ describe("DatePicker", () => { var testFormat = "YYYY-MM-DD"; var exactishFormat = "YYYY-MM-DD HH: ZZ"; var callback = sandbox.spy(); + var onInputErrorCallback = sandbox.spy(); + var datePicker = TestUtils.renderIntoDocument( - + ); var dateInput = datePicker.input; var nodeInput = ReactDOM.findDOMNode(dateInput); @@ -472,6 +479,7 @@ describe("DatePicker", () => { testFormat, exactishFormat, callback, + onInputErrorCallback, datePicker, dateInput, nodeInput @@ -580,6 +588,7 @@ describe("DatePicker", () => { TestUtils.Simulate.keyDown(data.nodeInput, getKey("Backspace")); TestUtils.Simulate.keyDown(data.nodeInput, getKey("Enter")); expect(data.callback.calledOnce).to.be.false; + expect(data.onInputErrorCallback.calledOnce).to.be.true; }); it("should not select excludeDates", () => { var data = getOnInputKeyDownStuff({ @@ -600,6 +609,28 @@ describe("DatePicker", () => { expect(data.callback.calledOnce).to.be.false; }); }); + describe("onInputKeyDown Escape", () => { + it("should not update the selected date if the date input manually it has something wrong", () => { + var data = getOnInputKeyDownStuff(); + TestUtils.Simulate.keyDown(data.nodeInput, { + key: "ArrowDown", + keyCode: 40, + which: 40 + }); + TestUtils.Simulate.keyDown(data.nodeInput, { + key: "Backspace", + keyCode: 8, + which: 8 + }); + TestUtils.Simulate.keyDown(data.nodeInput, { + key: "Escape", + keyCode: 27, + which: 27 + }); + expect(data.callback.calledOnce).to.be.false; + expect(data.onInputErrorCallback.calledOnce).to.be.true; + }); + }); it("should reset the keyboard selection when closed", () => { var data = getOnInputKeyDownStuff(); TestUtils.Simulate.keyDown(data.nodeInput, getKey("ArrowLeft"));