From 52b57404552773729836ca678986a0c9f2f16986 Mon Sep 17 00:00:00 2001 From: crisbeto Date: Thu, 4 Jan 2018 21:27:03 +0200 Subject: [PATCH] fix(select): don't restore focus unless an option was selected 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 a9d419492529..867d8ec909ee 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 c67f17be4c94..37847e66af3f 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(); } });