From 9dc43de540bebd50122a4b8637803bf4a1ebc717 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Tue, 23 Jan 2018 16:24:08 +0100 Subject: [PATCH] fix(select): don't restore focus unless an option was selected (#8964) Currently `mat-select` always restores focus to its trigger whenever the panel is closed. This can be problematic, because the user might've scrolled away and restoring focus would scroll the page back up. These changes switch to only restoring focus if the user made a selection. Fixes #8915. --- src/lib/select/select.spec.ts | 19 +++++++++++++++++++ src/lib/select/select.ts | 9 +++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/lib/select/select.spec.ts b/src/lib/select/select.spec.ts index a9d41949252..867d8ec909e 100644 --- a/src/lib/select/select.spec.ts +++ b/src/lib/select/select.spec.ts @@ -2519,6 +2519,25 @@ describe('MatSelect', () => { expect(document.activeElement).toBe(select, 'Expected trigger to be focused.'); })); + it('should not restore focus to the host element when clicking outside', fakeAsync(() => { + const fixture = TestBed.createComponent(BasicSelectWithoutForms); + const select = fixture.debugElement.nativeElement.querySelector('mat-select'); + + fixture.detectChanges(); + fixture.debugElement.query(By.css('.mat-select-trigger')).nativeElement.click(); + fixture.detectChanges(); + flush(); + + expect(document.activeElement).toBe(select, 'Expected trigger to be focused.'); + + select.blur(); // Blur manually since the programmatic click might not do it. + (overlayContainerElement.querySelector('.cdk-overlay-backdrop') as HTMLElement).click(); + fixture.detectChanges(); + flush(); + + expect(document.activeElement).not.toBe(select, 'Expected trigger not to be focused.'); + })); + it('should update the data binding before emitting the change event', fakeAsync(() => { const fixture = TestBed.createComponent(BasicSelectWithoutForms); const instance = fixture.componentInstance; diff --git a/src/lib/select/select.ts b/src/lib/select/select.ts index 10172d4cdc4..b2a57d5342f 100644 --- a/src/lib/select/select.ts +++ b/src/lib/select/select.ts @@ -298,7 +298,7 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit, ]; /** Whether the select is focused. */ - focused = false; + focused: boolean = false; /** A name for this control that can be used by `mat-form-field`. */ controlType = 'mat-select'; @@ -548,7 +548,6 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit, this._panelOpen = false; this._changeDetectorRef.markForCheck(); this._onTouched(); - this.focus(); } } @@ -715,8 +714,9 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit, * "blur" to the panel when it opens, causing a false positive. */ _onBlur() { + this.focused = false; + if (!this.disabled && !this.panelOpen) { - this.focused = false; this._onTouched(); this._changeDetectorRef.markForCheck(); this.stateChanges.next(); @@ -844,8 +844,9 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit, ).subscribe(event => { this._onSelect(event.source); - if (!this.multiple) { + if (!this.multiple && this._panelOpen) { this.close(); + this.focus(); } });