mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(autocomplete): close panel using alt + up arrow (#9341)
[Based on the accessibility guidelines](https://www.w3.org/TR/wai-aria-practices-1.1/#textbox-keyboard-interaction), the autocomplete panel can be closed using the alt + up arrow keyboard combo.
This commit is contained in:
committed by
Jeremy Elbourn
parent
4e8aa52d32
commit
2c192d0a57
@@ -129,8 +129,8 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
|
||||
/** The subscription for closing actions (some are bound to document). */
|
||||
private _closingActionsSubscription: Subscription;
|
||||
|
||||
/** Stream of escape keyboard events. */
|
||||
private _escapeEventStream = new Subject<void>();
|
||||
/** Stream of keyboard events that can close the panel. */
|
||||
private _closeKeyEventStream = new Subject<void>();
|
||||
|
||||
/** View -> model callback called when value changes */
|
||||
_onChange: (value: any) => void = () => {};
|
||||
@@ -152,7 +152,7 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
|
||||
|
||||
ngOnDestroy() {
|
||||
this._destroyPanel();
|
||||
this._escapeEventStream.complete();
|
||||
this._closeKeyEventStream.complete();
|
||||
}
|
||||
|
||||
/** Whether or not the autocomplete panel is open. */
|
||||
@@ -194,7 +194,7 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
|
||||
return merge(
|
||||
this.optionSelections,
|
||||
this.autocomplete._keyManager.tabOut.pipe(filter(() => this._panelOpen)),
|
||||
this._escapeEventStream,
|
||||
this._closeKeyEventStream,
|
||||
this._outsideClickStream,
|
||||
this._overlayRef ?
|
||||
this._overlayRef.detachments().pipe(filter(() => this._panelOpen)) :
|
||||
@@ -289,9 +289,11 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
|
||||
_handleKeydown(event: KeyboardEvent): void {
|
||||
const keyCode = event.keyCode;
|
||||
|
||||
if (keyCode === ESCAPE && this.panelOpen) {
|
||||
// Close when pressing ESCAPE or ALT + UP_ARROW, based on the a11y guidelines.
|
||||
// See: https://www.w3.org/TR/wai-aria-practices-1.1/#textbox-keyboard-interaction
|
||||
if (this.panelOpen && (keyCode === ESCAPE || (keyCode === UP_ARROW && event.altKey))) {
|
||||
this._resetActiveItem();
|
||||
this._escapeEventStream.next();
|
||||
this._closeKeyEventStream.next();
|
||||
event.stopPropagation();
|
||||
} else if (this.activeOption && keyCode === ENTER && this.panelOpen) {
|
||||
this.activeOption._selectViaInteraction();
|
||||
|
||||
@@ -902,6 +902,25 @@ describe('MatAutocomplete', () => {
|
||||
expect(stopPropagationSpy).toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
it('should close the panel when pressing ALT + UP_ARROW', fakeAsync(() => {
|
||||
const trigger = fixture.componentInstance.trigger;
|
||||
const upArrowEvent = createKeyboardEvent('keydown', UP_ARROW);
|
||||
Object.defineProperty(upArrowEvent, 'altKey', {get: () => true});
|
||||
|
||||
input.focus();
|
||||
flush();
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(document.activeElement).toBe(input, 'Expected input to be focused.');
|
||||
expect(trigger.panelOpen).toBe(true, 'Expected panel to be open.');
|
||||
|
||||
trigger._handleKeydown(upArrowEvent);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(document.activeElement).toBe(input, 'Expected input to continue to be focused.');
|
||||
expect(trigger.panelOpen).toBe(false, 'Expected panel to be closed.');
|
||||
}));
|
||||
|
||||
it('should close the panel when tabbing away from a trigger without results', fakeAsync(() => {
|
||||
fixture.componentInstance.states = [];
|
||||
fixture.componentInstance.filteredStates = [];
|
||||
|
||||
Reference in New Issue
Block a user