Skip to content

Commit

Permalink
refactor(datepicker): use common overlay keyboard handling (#8941)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
crisbeto authored and jelbourn committed Jan 8, 2018
1 parent c349c58 commit b8ff582
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 36 deletions.
28 changes: 7 additions & 21 deletions src/lib/datepicker/datepicker.spec.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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.');

const keyboardEvent = createKeyboardEvent('keydown', ESCAPE);
const stopPropagationSpy = spyOn(keyboardEvent, 'stopPropagation').and.callThrough();
expect(testComponent.datepicker.opened).toBe(true, 'Expected datepicker to be open.');

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;
Expand Down
21 changes: 6 additions & 15 deletions src/lib/datepicker/datepicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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();
}
}
}


Expand Down Expand Up @@ -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. */
Expand Down

0 comments on commit b8ff582

Please sign in to comment.