mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
refactor(datepicker): use common overlay keyboard handling (#8941)
Switches the datepicker to use the `OverlayKeyboardDispatcher`, rather than managing the keyboard logic itself. This simplifies things and handles the cases where the popup won't close if it lost focus.
This commit is contained in:
committed by
Jeremy Elbourn
parent
c349c587a5
commit
b8ff582fc9
@@ -1,12 +1,6 @@
|
||||
import {ENTER, ESCAPE, RIGHT_ARROW} from '@angular/cdk/keycodes';
|
||||
import {OverlayContainer, Overlay, ScrollDispatcher} from '@angular/cdk/overlay';
|
||||
import {
|
||||
createKeyboardEvent,
|
||||
dispatchEvent,
|
||||
dispatchFakeEvent,
|
||||
dispatchKeyboardEvent,
|
||||
dispatchMouseEvent,
|
||||
} from '@angular/cdk/testing';
|
||||
import {dispatchFakeEvent, dispatchKeyboardEvent, dispatchMouseEvent} from '@angular/cdk/testing';
|
||||
import {Component, ViewChild} from '@angular/core';
|
||||
import {fakeAsync, flush, ComponentFixture, inject, TestBed} from '@angular/core/testing';
|
||||
import {FormControl, FormsModule, ReactiveFormsModule} from '@angular/forms';
|
||||
@@ -157,26 +151,18 @@ describe('MatDatepicker', () => {
|
||||
expect(parseInt(getComputedStyle(popup).height as string)).toBe(0);
|
||||
});
|
||||
|
||||
it('should close the popup when pressing ESCAPE', () => {
|
||||
it('should close the popup when pressing ESCAPE', fakeAsync(() => {
|
||||
testComponent.datepicker.open();
|
||||
fixture.detectChanges();
|
||||
|
||||
let content = document.querySelector('.cdk-overlay-pane mat-datepicker-content')!;
|
||||
expect(content).toBeTruthy('Expected datepicker to be open.');
|
||||
expect(testComponent.datepicker.opened).toBe(true, 'Expected datepicker to be open.');
|
||||
|
||||
const keyboardEvent = createKeyboardEvent('keydown', ESCAPE);
|
||||
const stopPropagationSpy = spyOn(keyboardEvent, 'stopPropagation').and.callThrough();
|
||||
|
||||
dispatchEvent(content, keyboardEvent);
|
||||
dispatchKeyboardEvent(document.body, 'keydown', ESCAPE);
|
||||
fixture.detectChanges();
|
||||
flush();
|
||||
|
||||
content = document.querySelector('.cdk-overlay-pane mat-datepicker-content')!;
|
||||
|
||||
expect(content).toBeFalsy('Expected datepicker to be closed.');
|
||||
expect(stopPropagationSpy).toHaveBeenCalled();
|
||||
expect(keyboardEvent.defaultPrevented)
|
||||
.toBe(true, 'Expected default ESCAPE action to be prevented.');
|
||||
});
|
||||
expect(testComponent.datepicker.opened).toBe(false, 'Expected datepicker to be closed.');
|
||||
}));
|
||||
|
||||
it('close should close dialog', fakeAsync(() => {
|
||||
testComponent.touch = true;
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
} from '@angular/cdk/overlay';
|
||||
import {ComponentPortal} from '@angular/cdk/portal';
|
||||
import {take} from 'rxjs/operators/take';
|
||||
import {filter} from 'rxjs/operators/filter';
|
||||
import {
|
||||
AfterContentInit,
|
||||
ChangeDetectionStrategy,
|
||||
@@ -83,7 +84,6 @@ export const MAT_DATEPICKER_SCROLL_STRATEGY_PROVIDER = {
|
||||
host: {
|
||||
'class': 'mat-datepicker-content',
|
||||
'[class.mat-datepicker-content-touch]': 'datepicker.touchUi',
|
||||
'(keydown)': '_handleKeydown($event)',
|
||||
},
|
||||
exportAs: 'matDatepickerContent',
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
@@ -98,18 +98,6 @@ export class MatDatepickerContent<D> implements AfterContentInit {
|
||||
ngAfterContentInit() {
|
||||
this._calendar._focusActiveCell();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles keydown event on datepicker content.
|
||||
* @param event The event.
|
||||
*/
|
||||
_handleKeydown(event: KeyboardEvent): void {
|
||||
if (event.keyCode === ESCAPE) {
|
||||
this.datepicker.close();
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -382,8 +370,11 @@ export class MatDatepicker<D> implements OnDestroy {
|
||||
|
||||
this._popupRef = this._overlay.create(overlayConfig);
|
||||
|
||||
merge(this._popupRef.backdropClick(), this._popupRef.detachments())
|
||||
.subscribe(() => this.close());
|
||||
merge(
|
||||
this._popupRef.backdropClick(),
|
||||
this._popupRef.detachments(),
|
||||
this._popupRef.keydownEvents().pipe(filter(event => event.keyCode === ESCAPE))
|
||||
).subscribe(() => this.close());
|
||||
}
|
||||
|
||||
/** Create the popup PositionStrategy. */
|
||||
|
||||
Reference in New Issue
Block a user