Skip to content

Commit 8e63656

Browse files
crisbetojelbourn
authored andcommitted
fix(datepicker): multiple dialog open if the user holds down enter key (#12238)
Fixes the case where the user might be holding down the enter key for a datepicker in touch mode, which could cause it to open multiple dialogs at the same time.
1 parent 1b19b93 commit 8e63656

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

src/lib/datepicker/datepicker.spec.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
dispatchMouseEvent,
99
} from '@angular/cdk/testing';
1010
import {Component, FactoryProvider, Type, ValueProvider, ViewChild} from '@angular/core';
11-
import {ComponentFixture, fakeAsync, flush, inject, TestBed} from '@angular/core/testing';
11+
import {ComponentFixture, fakeAsync, flush, inject, TestBed, tick} from '@angular/core/testing';
1212
import {FormControl, FormsModule, ReactiveFormsModule} from '@angular/forms';
1313
import {
1414
DEC,
@@ -102,7 +102,7 @@ describe('MatDatepicker', () => {
102102
expect(document.querySelector('.cdk-overlay-pane.mat-datepicker-popup')).not.toBeNull();
103103
});
104104

105-
it('open touch should open dialog', () => {
105+
it('touch should open dialog', () => {
106106
testComponent.touch = true;
107107
fixture.detectChanges();
108108

@@ -115,6 +115,28 @@ describe('MatDatepicker', () => {
115115
.not.toBeNull();
116116
});
117117

118+
it('should not be able to open more than one dialog', fakeAsync(() => {
119+
testComponent.touch = true;
120+
fixture.detectChanges();
121+
122+
expect(document.querySelectorAll('.mat-datepicker-dialog').length).toBe(0);
123+
124+
testComponent.datepicker.open();
125+
fixture.detectChanges();
126+
tick(500);
127+
fixture.detectChanges();
128+
129+
dispatchKeyboardEvent(document.querySelector('.mat-calendar-body')!, 'keydown', ENTER);
130+
fixture.detectChanges();
131+
tick(100);
132+
133+
testComponent.datepicker.open();
134+
tick(500);
135+
fixture.detectChanges();
136+
137+
expect(document.querySelectorAll('.mat-datepicker-dialog').length).toBe(1);
138+
}));
139+
118140
it('should open datepicker if opened input is set to true', fakeAsync(() => {
119141
testComponent.opened = true;
120142
fixture.detectChanges();

src/lib/datepicker/datepicker.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,14 @@ export class MatDatepicker<D> implements OnDestroy, CanColor {
380380

381381
/** Open the calendar as a dialog. */
382382
private _openAsDialog(): void {
383+
// Usually this would be handled by `open` which ensures that we can only have one overlay
384+
// open at a time, however since we reset the variables in async handlers some overlays
385+
// may slip through if the user opens and closes multiple times in quick succession (e.g.
386+
// by holding down the enter key).
387+
if (this._dialogRef) {
388+
this._dialogRef.close();
389+
}
390+
383391
this._dialogRef = this._dialog.open<MatDatepickerContent<D>>(MatDatepickerContent, {
384392
direction: this._dir ? this._dir.value : 'ltr',
385393
viewContainerRef: this._viewContainerRef,

0 commit comments

Comments
 (0)