Skip to content

Commit 0b2757c

Browse files
authored
fix(datepicker): keyboard fixes (enter matches click behavior & corre… (#7370)
* fix(datepicker): keyboard fixes (enter matches click behavior & correct up and down arrow behavior in year mode). * fix tests
1 parent e7b412a commit 0b2757c

File tree

3 files changed

+62
-20
lines changed

3 files changed

+62
-20
lines changed

src/lib/datepicker/calendar.spec.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ import {
2020
JUL,
2121
JUN,
2222
MAR,
23-
MAY,
2423
MatNativeDateModule,
24+
MAY,
2525
NOV,
26+
OCT,
2627
SEP,
2728
} from '@angular/material/core';
2829
import {By} from '@angular/platform-browser';
@@ -341,46 +342,46 @@ describe('MatCalendar', () => {
341342
dispatchKeyboardEvent(calendarBodyEl, 'keydown', UP_ARROW);
342343
fixture.detectChanges();
343344

344-
expect(calendarInstance._activeDate).toEqual(new Date(2016, AUG, 31));
345+
expect(calendarInstance._activeDate).toEqual(new Date(2016, SEP, 30));
345346

346347
calendarInstance._activeDate = new Date(2017, JUL, 1);
347348
fixture.detectChanges();
348349

349350
dispatchKeyboardEvent(calendarBodyEl, 'keydown', UP_ARROW);
350351
fixture.detectChanges();
351352

352-
expect(calendarInstance._activeDate).toEqual(new Date(2016, JUL, 1));
353+
expect(calendarInstance._activeDate).toEqual(new Date(2017, MAR, 1));
353354

354355
calendarInstance._activeDate = new Date(2017, DEC, 10);
355356
fixture.detectChanges();
356357

357358
dispatchKeyboardEvent(calendarBodyEl, 'keydown', UP_ARROW);
358359
fixture.detectChanges();
359360

360-
expect(calendarInstance._activeDate).toEqual(new Date(2017, MAY, 10));
361+
expect(calendarInstance._activeDate).toEqual(new Date(2017, AUG, 10));
361362
});
362363

363364
it('should go down a row on down arrow press', () => {
364365
dispatchKeyboardEvent(calendarBodyEl, 'keydown', DOWN_ARROW);
365366
fixture.detectChanges();
366367

367-
expect(calendarInstance._activeDate).toEqual(new Date(2017, AUG, 31));
368+
expect(calendarInstance._activeDate).toEqual(new Date(2017, MAY, 31));
368369

369370
calendarInstance._activeDate = new Date(2017, JUN, 1);
370371
fixture.detectChanges();
371372

372373
dispatchKeyboardEvent(calendarBodyEl, 'keydown', DOWN_ARROW);
373374
fixture.detectChanges();
374375

375-
expect(calendarInstance._activeDate).toEqual(new Date(2018, JUN, 1));
376+
expect(calendarInstance._activeDate).toEqual(new Date(2017, OCT, 1));
376377

377378
calendarInstance._activeDate = new Date(2017, SEP, 30);
378379
fixture.detectChanges();
379380

380381
dispatchKeyboardEvent(calendarBodyEl, 'keydown', DOWN_ARROW);
381382
fixture.detectChanges();
382383

383-
expect(calendarInstance._activeDate).toEqual(new Date(2018, FEB, 28));
384+
expect(calendarInstance._activeDate).toEqual(new Date(2018, JAN, 30));
384385
});
385386

386387
it('should go to first month of the year on home press', () => {

src/lib/datepicker/calendar.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ export class MatCalendar<D> implements AfterContentInit, OnDestroy, OnChanges {
312312
case ENTER:
313313
if (this._dateFilterForViews(this._activeDate)) {
314314
this._dateSelected(this._activeDate);
315+
this._userSelected();
315316
// Prevent unexpected default actions such as form submission.
316317
event.preventDefault();
317318
}
@@ -375,23 +376,17 @@ export class MatCalendar<D> implements AfterContentInit, OnDestroy, OnChanges {
375376
* calendar table.
376377
*/
377378
private _prevMonthInSameCol(date: D): D {
378-
// Determine how many months to jump forward given that there are 2 empty slots at the beginning
379-
// of each year.
380-
let increment = this._dateAdapter.getMonth(date) <= 4 ? -5 :
381-
(this._dateAdapter.getMonth(date) >= 7 ? -7 : -12);
382-
return this._dateAdapter.addCalendarMonths(date, increment);
379+
// Decrement by 4 since there are 4 months per row.
380+
return this._dateAdapter.addCalendarMonths(date, -4);
383381
}
384382

385383
/**
386384
* Determine the date for the month that comes after the given month in the same column in the
387385
* calendar table.
388386
*/
389387
private _nextMonthInSameCol(date: D): D {
390-
// Determine how many months to jump forward given that there are 2 empty slots at the beginning
391-
// of each year.
392-
let increment = this._dateAdapter.getMonth(date) <= 4 ? 7 :
393-
(this._dateAdapter.getMonth(date) >= 7 ? 5 : 12);
394-
return this._dateAdapter.addCalendarMonths(date, increment);
388+
// Increment by 4 since there are 4 months per row.
389+
return this._dateAdapter.addCalendarMonths(date, 4);
395390
}
396391

397392
/**

src/lib/datepicker/datepicker.spec.ts

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import {ESCAPE} from '@angular/cdk/keycodes';
1+
import {ENTER, ESCAPE, RIGHT_ARROW} from '@angular/cdk/keycodes';
22
import {OverlayContainer} from '@angular/cdk/overlay';
33
import {
44
createKeyboardEvent,
55
dispatchEvent,
66
dispatchFakeEvent,
7+
dispatchKeyboardEvent,
78
dispatchMouseEvent,
89
} from '@angular/cdk/testing';
910
import {Component, ViewChild} from '@angular/core';
@@ -203,7 +204,7 @@ describe('MatDatepicker', () => {
203204
});
204205
}));
205206

206-
it('setting selected should update input and close calendar', async(() => {
207+
it('setting selected via click should update input and close calendar', async(() => {
207208
testComponent.touch = true;
208209
fixture.detectChanges();
209210

@@ -223,8 +224,31 @@ describe('MatDatepicker', () => {
223224
});
224225
}));
225226

227+
it('setting selected via enter press should update input and close calendar', () => {
228+
testComponent.touch = true;
229+
fixture.detectChanges();
230+
231+
testComponent.datepicker.open();
232+
fixture.detectChanges();
233+
234+
expect(document.querySelector('mat-dialog-container')).not.toBeNull();
235+
expect(testComponent.datepickerInput.value).toEqual(new Date(2020, JAN, 1));
236+
237+
let calendarBodyEl = document.querySelector('.mat-calendar-content') as HTMLElement;
238+
239+
dispatchKeyboardEvent(calendarBodyEl, 'keydown', RIGHT_ARROW);
240+
fixture.detectChanges();
241+
dispatchKeyboardEvent(calendarBodyEl, 'keydown', ENTER);
242+
fixture.detectChanges();
243+
244+
fixture.whenStable().then(() => {
245+
expect(document.querySelector('mat-dialog-container')).toBeNull();
246+
expect(testComponent.datepickerInput.value).toEqual(new Date(2020, JAN, 2));
247+
});
248+
});
249+
226250
it('clicking the currently selected date should close the calendar ' +
227-
'without firing selectedChanged', () => {
251+
'without firing selectedChanged', () => {
228252
const selectedChangedSpy =
229253
spyOn(testComponent.datepicker.selectedChanged, 'emit').and.callThrough();
230254

@@ -246,6 +270,28 @@ describe('MatDatepicker', () => {
246270
expect(testComponent.datepickerInput.value).toEqual(new Date(2020, JAN, 2));
247271
});
248272

273+
it('pressing enter on the currently selected date should close the calendar without ' +
274+
'firing selectedChanged', () => {
275+
const selectedChangedSpy =
276+
spyOn(testComponent.datepicker.selectedChanged, 'emit').and.callThrough();
277+
278+
testComponent.datepicker.open();
279+
fixture.detectChanges();
280+
281+
let calendarBodyEl = document.querySelector('.mat-calendar-content') as HTMLElement;
282+
expect(calendarBodyEl).not.toBeNull();
283+
expect(testComponent.datepickerInput.value).toEqual(new Date(2020, JAN, 1));
284+
285+
dispatchKeyboardEvent(calendarBodyEl, 'keydown', ENTER);
286+
fixture.detectChanges();
287+
288+
fixture.whenStable().then(() => {
289+
expect(selectedChangedSpy.calls.count()).toEqual(0);
290+
expect(document.querySelector('mat-dialog-container')).toBeNull();
291+
expect(testComponent.datepickerInput.value).toEqual(new Date(2020, JAN, 1));
292+
});
293+
});
294+
249295
it('startAt should fallback to input value', () => {
250296
expect(testComponent.datepicker.startAt).toEqual(new Date(2020, JAN, 1));
251297
});

0 commit comments

Comments
 (0)