Skip to content

Commit 9dc43de

Browse files
crisbetojelbourn
authored andcommitted
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.
1 parent a6f9fc2 commit 9dc43de

File tree

2 files changed

+24
-4
lines changed

2 files changed

+24
-4
lines changed

src/lib/select/select.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2519,6 +2519,25 @@ describe('MatSelect', () => {
25192519
expect(document.activeElement).toBe(select, 'Expected trigger to be focused.');
25202520
}));
25212521

2522+
it('should not restore focus to the host element when clicking outside', fakeAsync(() => {
2523+
const fixture = TestBed.createComponent(BasicSelectWithoutForms);
2524+
const select = fixture.debugElement.nativeElement.querySelector('mat-select');
2525+
2526+
fixture.detectChanges();
2527+
fixture.debugElement.query(By.css('.mat-select-trigger')).nativeElement.click();
2528+
fixture.detectChanges();
2529+
flush();
2530+
2531+
expect(document.activeElement).toBe(select, 'Expected trigger to be focused.');
2532+
2533+
select.blur(); // Blur manually since the programmatic click might not do it.
2534+
(overlayContainerElement.querySelector('.cdk-overlay-backdrop') as HTMLElement).click();
2535+
fixture.detectChanges();
2536+
flush();
2537+
2538+
expect(document.activeElement).not.toBe(select, 'Expected trigger not to be focused.');
2539+
}));
2540+
25222541
it('should update the data binding before emitting the change event', fakeAsync(() => {
25232542
const fixture = TestBed.createComponent(BasicSelectWithoutForms);
25242543
const instance = fixture.componentInstance;

src/lib/select/select.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
298298
];
299299

300300
/** Whether the select is focused. */
301-
focused = false;
301+
focused: boolean = false;
302302

303303
/** A name for this control that can be used by `mat-form-field`. */
304304
controlType = 'mat-select';
@@ -548,7 +548,6 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
548548
this._panelOpen = false;
549549
this._changeDetectorRef.markForCheck();
550550
this._onTouched();
551-
this.focus();
552551
}
553552
}
554553

@@ -715,8 +714,9 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
715714
* "blur" to the panel when it opens, causing a false positive.
716715
*/
717716
_onBlur() {
717+
this.focused = false;
718+
718719
if (!this.disabled && !this.panelOpen) {
719-
this.focused = false;
720720
this._onTouched();
721721
this._changeDetectorRef.markForCheck();
722722
this.stateChanges.next();
@@ -844,8 +844,9 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
844844
).subscribe(event => {
845845
this._onSelect(event.source);
846846

847-
if (!this.multiple) {
847+
if (!this.multiple && this._panelOpen) {
848848
this.close();
849+
this.focus();
849850
}
850851
});
851852

0 commit comments

Comments
 (0)