Skip to content

Commit 850006b

Browse files
committed
feat(datepicker): Select a typed date on losing focus
1 parent ae6ba5a commit 850006b

File tree

2 files changed

+76
-3
lines changed

2 files changed

+76
-3
lines changed

src/components/Datepicker.vue

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -353,11 +353,15 @@ export default {
353353
this.setInitialView()
354354
}
355355
},
356-
isActive(hasJustBecomeActive) {
356+
isActive(hasJustBecomeActive, isNoLongerActive) {
357357
if (hasJustBecomeActive && this.inline) {
358358
this.setNavElementsFocusedIndex()
359359
this.tabToCorrectInlineCell()
360360
}
361+
362+
if (isNoLongerActive && this.typeable) {
363+
this.setTypedDateOnLosingFocus()
364+
}
361365
},
362366
latestValidTypedDate(date) {
363367
this.setPageDate(date)
@@ -721,8 +725,30 @@ export default {
721725
this.slideDuration = parseFloat(durationInSecs) * 1000
722726
},
723727
/**
724-
* Set the datepicker value (and, if typeable, update `latestValidTypedDate`)
725-
* @param {Date|String|Number|null} date
728+
* Selects the typed date when the datepicker loses focus, provided it's valid and differs from the current selected date
729+
*/
730+
setTypedDateOnLosingFocus() {
731+
const parsedDate = this.$refs.dateInput.parseInput()
732+
const date = this.utils.isValidDate(parsedDate) ? parsedDate : null
733+
const hasChanged = () => {
734+
if (!this.selectedDate && !date) {
735+
return false
736+
}
737+
738+
if (this.selectedDate && date) {
739+
return date.valueOf() !== this.selectedDate.valueOf()
740+
}
741+
742+
return true
743+
}
744+
745+
if (hasChanged()) {
746+
this.setValue(date)
747+
this.$emit('selected', date)
748+
}
749+
},
750+
/**
751+
* Set the datepicker value (and, if typeable, update `latestValidTypedDate`) * @param {Date|String|Number|null} date
726752
*/
727753
setValue(date) {
728754
this.selectedDate = date || null

test/unit/specs/DateInput/typedDates.spec.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,8 @@ describe('Datepicker mounted to document body', () => {
321321
let wrapper
322322

323323
beforeEach(() => {
324+
jest.useFakeTimers()
325+
324326
wrapper = mount(Datepicker, {
325327
attachTo: document.body,
326328
propsData: {
@@ -330,6 +332,8 @@ describe('Datepicker mounted to document body', () => {
330332
})
331333

332334
afterEach(() => {
335+
jest.clearAllTimers()
336+
333337
wrapper.destroy()
334338
})
335339

@@ -391,4 +395,47 @@ describe('Datepicker mounted to document body', () => {
391395

392396
expect(document.activeElement).toBe(input.element)
393397
})
398+
399+
it("selects the typed date when the calendar loses focus, provided it's valid and differs from the current selected date", async () => {
400+
const input = wrapper.find('input')
401+
402+
// Invalid date
403+
await input.trigger('click')
404+
jest.advanceTimersByTime(250)
405+
406+
await input.setValue('invalid date')
407+
await input.trigger('keyup')
408+
409+
await document.activeElement.blur()
410+
jest.advanceTimersByTime(250)
411+
412+
expect(input.element.value).toEqual('')
413+
expect(wrapper.emitted('selected')).toBeFalsy()
414+
415+
// Valid date
416+
await input.trigger('click')
417+
jest.advanceTimersByTime(250)
418+
419+
await input.setValue('2 jan 22')
420+
await input.trigger('keyup')
421+
422+
await document.activeElement.blur()
423+
jest.advanceTimersByTime(250)
424+
425+
expect(input.element.value).toEqual('02 Jan 2022')
426+
expect(wrapper.emitted('selected')).toBeTruthy()
427+
428+
// Unchanged date
429+
await input.trigger('click')
430+
jest.advanceTimersByTime(250)
431+
432+
await input.setValue('2 jan 22')
433+
await input.trigger('keyup')
434+
435+
await document.activeElement.blur()
436+
jest.advanceTimersByTime(250)
437+
438+
expect(input.element.value).toEqual('02 Jan 2022')
439+
expect(wrapper.emitted('selected')).toHaveLength(1)
440+
})
394441
})

0 commit comments

Comments
 (0)