Skip to content

Commit c6ad1f8

Browse files
crisbetojosephperrott
authored andcommitted
fix(select): losing focus position when tabbing away after clicking inside multi select (#10905)
1 parent 0f7d503 commit c6ad1f8

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

src/lib/select/select.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,25 @@ describe('MatSelect', () => {
912912
expect(fixture.componentInstance.select.panelOpen).toBe(false);
913913
}));
914914

915+
it('should restore focus to the host before tabbing away', fakeAsync(() => {
916+
const select = fixture.nativeElement.querySelector('.mat-select');
917+
918+
trigger.click();
919+
fixture.detectChanges();
920+
flush();
921+
922+
expect(fixture.componentInstance.select.panelOpen).toBe(true);
923+
924+
// Use a spy since focus can be flaky in unit tests.
925+
spyOn(select, 'focus').and.callThrough();
926+
927+
dispatchKeyboardEvent(trigger, 'keydown', TAB);
928+
fixture.detectChanges();
929+
flush();
930+
931+
expect(select.focus).toHaveBeenCalled();
932+
}));
933+
915934
it('should close when tabbing out from inside the panel', fakeAsync(() => {
916935
trigger.click();
917936
fixture.detectChanges();

src/lib/select/select.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -826,7 +826,13 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
826826
.withVerticalOrientation()
827827
.withHorizontalOrientation(this._isRtl() ? 'rtl' : 'ltr');
828828

829-
this._keyManager.tabOut.pipe(takeUntil(this._destroy)).subscribe(() => this.close());
829+
this._keyManager.tabOut.pipe(takeUntil(this._destroy)).subscribe(() => {
830+
// Restore focus to the trigger before closing. Ensures that the focus
831+
// position won't be lost if the user got focus into the overlay.
832+
this.focus();
833+
this.close();
834+
});
835+
830836
this._keyManager.change.pipe(takeUntil(this._destroy)).subscribe(() => {
831837
if (this._panelOpen && this.panel) {
832838
this._scrollActiveOptionIntoView();

0 commit comments

Comments
 (0)