From 55bf5f7cca1d4365776ae672e2306d255e11e765 Mon Sep 17 00:00:00 2001 From: crisbeto Date: Thu, 4 Jan 2018 12:52:26 +0200 Subject: [PATCH] fix(autocomplete): prevent opening using arrow keys on readonly input A while back we started blocking being able to open an autocomplete by focusing a readonly input, however that didn't cover opening using the keyboard shortcuts. These changes also prevent users from being able to open using the keyboard. Fixes #9227. --- src/lib/autocomplete/autocomplete-trigger.ts | 12 +++++++++--- src/lib/autocomplete/autocomplete.spec.ts | 13 +++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/lib/autocomplete/autocomplete-trigger.ts b/src/lib/autocomplete/autocomplete-trigger.ts index 9ee22496d39c..0da3a6be383d 100644 --- a/src/lib/autocomplete/autocomplete-trigger.ts +++ b/src/lib/autocomplete/autocomplete-trigger.ts @@ -294,7 +294,7 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnDestroy { if (this.panelOpen || keyCode === TAB) { this.autocomplete._keyManager.onKeydown(event); - } else if (isArrowKey) { + } else if (isArrowKey && this._canOpen()) { this.openPanel(); } @@ -308,14 +308,14 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnDestroy { // We need to ensure that the input is focused, because IE will fire the `input` // event on focus/blur/load if the input has a placeholder. See: // https://connect.microsoft.com/IE/feedback/details/885747/ - if (document.activeElement === event.target) { + if (this._canOpen() && document.activeElement === event.target) { this._onChange((event.target as HTMLInputElement).value); this.openPanel(); } } _handleFocus(): void { - if (!this._element.nativeElement.readOnly) { + if (this._canOpen()) { this._attachOverlay(); this._floatLabel(true); } @@ -513,4 +513,10 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnDestroy { this.autocomplete._keyManager.setActiveItem(-1); } + /** Determines whether the panel can be opened. */ + private _canOpen(): boolean { + const element: HTMLInputElement = this._element.nativeElement; + return !element.readOnly && !element.disabled; + } + } diff --git a/src/lib/autocomplete/autocomplete.spec.ts b/src/lib/autocomplete/autocomplete.spec.ts index 3425f263732a..ab36e7aed644 100644 --- a/src/lib/autocomplete/autocomplete.spec.ts +++ b/src/lib/autocomplete/autocomplete.spec.ts @@ -134,6 +134,19 @@ describe('MatAutocomplete', () => { expect(trigger.panelOpen).toBe(false, 'Expected panel to stay closed.'); })); + it('should not open using the arrow keys when the input is readonly', fakeAsync(() => { + const trigger = fixture.componentInstance.trigger; + input.readOnly = true; + fixture.detectChanges(); + + expect(trigger.panelOpen).toBe(false, 'Expected panel state to start out closed.'); + dispatchKeyboardEvent(input, 'keydown', DOWN_ARROW); + flush(); + + fixture.detectChanges(); + expect(trigger.panelOpen).toBe(false, 'Expected panel to stay closed.'); + })); + it('should open the panel programmatically', () => { expect(fixture.componentInstance.trigger.panelOpen) .toBe(false, `Expected panel state to start out closed.`);