From 77aeb0c47450420c57d336b946f7909d710e5b78 Mon Sep 17 00:00:00 2001 From: crisbeto Date: Sat, 23 Sep 2017 15:55:25 +0200 Subject: [PATCH] fix(autocomplete): empty not cleaning up on tab Fixes an issue that caused the autocomplete not to be cleaned up when the user tabs away, if there were no results when the autocomplete was open. Fixes #7268. --- src/lib/autocomplete/autocomplete-trigger.ts | 12 ++++---- src/lib/autocomplete/autocomplete.spec.ts | 29 ++++++++++++++++++-- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/lib/autocomplete/autocomplete-trigger.ts b/src/lib/autocomplete/autocomplete-trigger.ts index 89e8d3487b90..9d1b1241f660 100644 --- a/src/lib/autocomplete/autocomplete-trigger.ts +++ b/src/lib/autocomplete/autocomplete-trigger.ts @@ -7,7 +7,7 @@ */ import {Directionality} from '@angular/cdk/bidi'; -import {DOWN_ARROW, ENTER, ESCAPE, UP_ARROW} from '@angular/cdk/keycodes'; +import {DOWN_ARROW, ENTER, ESCAPE, UP_ARROW, TAB} from '@angular/cdk/keycodes'; import { ConnectedPositionStrategy, Overlay, @@ -270,19 +270,21 @@ export class MdAutocompleteTrigger implements ControlValueAccessor, OnDestroy { } _handleKeydown(event: KeyboardEvent): void { - if (event.keyCode === ESCAPE && this.panelOpen) { + const keyCode = event.keyCode; + + if (keyCode === ESCAPE && this.panelOpen) { this._resetActiveItem(); this.closePanel(); event.stopPropagation(); - } else if (this.activeOption && event.keyCode === ENTER && this.panelOpen) { + } else if (this.activeOption && keyCode === ENTER && this.panelOpen) { this.activeOption._selectViaInteraction(); this._resetActiveItem(); event.preventDefault(); } else { const prevActiveItem = this.autocomplete._keyManager.activeItem; - const isArrowKey = event.keyCode === UP_ARROW || event.keyCode === DOWN_ARROW; + const isArrowKey = keyCode === UP_ARROW || keyCode === DOWN_ARROW; - if (this.panelOpen) { + if (this.panelOpen || keyCode === TAB) { this.autocomplete._keyManager.onKeydown(event); } else if (isArrowKey) { this.openPanel(); diff --git a/src/lib/autocomplete/autocomplete.spec.ts b/src/lib/autocomplete/autocomplete.spec.ts index e4886f42dd1d..c99c9865eb6b 100644 --- a/src/lib/autocomplete/autocomplete.spec.ts +++ b/src/lib/autocomplete/autocomplete.spec.ts @@ -1,9 +1,14 @@ import {Direction, Directionality} from '@angular/cdk/bidi'; -import {DOWN_ARROW, ENTER, ESCAPE, SPACE, UP_ARROW} from '@angular/cdk/keycodes'; +import {DOWN_ARROW, ENTER, ESCAPE, SPACE, UP_ARROW, TAB} from '@angular/cdk/keycodes'; import {OverlayContainer} from '@angular/cdk/overlay'; import {map, RxChain, startWith} from '@angular/cdk/rxjs'; import {ScrollDispatcher} from '@angular/cdk/scrolling'; -import {createKeyboardEvent, dispatchFakeEvent, typeInElement} from '@angular/cdk/testing'; +import { + createKeyboardEvent, + dispatchKeyboardEvent, + dispatchFakeEvent, + typeInElement, +} from '@angular/cdk/testing'; import { ChangeDetectionStrategy, Component, @@ -944,6 +949,26 @@ describe('MdAutocomplete', () => { }); })); + it('should close the panel when tabbing away from a trigger without results', async(() => { + const trigger = fixture.componentInstance.trigger; + + fixture.componentInstance.states = []; + fixture.componentInstance.filteredStates = []; + fixture.detectChanges(); + input.focus(); + + fixture.whenStable().then(() => { + expect(overlayContainerElement.querySelector('.mat-autocomplete-panel')) + .toBeTruthy('Expected panel to be rendered.'); + + dispatchKeyboardEvent(input, 'keydown', TAB); + fixture.detectChanges(); + + expect(overlayContainerElement.querySelector('.mat-autocomplete-panel')) + .toBeFalsy('Expected panel to be removed.'); + }); + })); + it('should reset the active option when closing with the escape key', fakeAsync(() => { const trigger = fixture.componentInstance.trigger;