Skip to content

Commit b450db7

Browse files
committed
feat(material/tabs): add method for programmatically setting focus
Adds a method that allows for focus to be moved to a particular tab. This is usually tricky, because all of the DOM elements are hidden away inside the tab group template. Fixes #15007.
1 parent 71b7b15 commit b450db7

File tree

4 files changed

+60
-2
lines changed

4 files changed

+60
-2
lines changed

src/material-experimental/mdc-tabs/tab-group.spec.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@ import {By} from '@angular/platform-browser';
66
import {BrowserAnimationsModule, NoopAnimationsModule} from '@angular/platform-browser/animations';
77
import {CommonModule} from '@angular/common';
88
import {Observable} from 'rxjs';
9-
import {MAT_TABS_CONFIG, MatTab, MatTabGroup, MatTabHeaderPosition, MatTabsModule} from './index';
9+
import {
10+
MAT_TABS_CONFIG,
11+
MatTab,
12+
MatTabGroup,
13+
MatTabHeaderPosition,
14+
MatTabsModule,
15+
MatTabHeader,
16+
} from './index';
1017

1118

1219
describe('MDC-based MatTabGroup', () => {
@@ -300,6 +307,21 @@ describe('MDC-based MatTabGroup', () => {
300307
.toBe(true);
301308
});
302309

310+
it('should be able to programmatically focus a particular tab', () => {
311+
fixture.detectChanges();
312+
const tabGroup: MatTabGroup =
313+
fixture.debugElement.query(By.css('mat-tab-group')).componentInstance;
314+
const tabHeader: MatTabHeader =
315+
fixture.debugElement.query(By.css('mat-tab-header')).componentInstance;
316+
317+
expect(tabHeader.focusIndex).not.toBe(3);
318+
319+
tabGroup.focusTab(3);
320+
fixture.detectChanges();
321+
322+
expect(tabHeader.focusIndex).not.toBe(3);
323+
});
324+
303325
});
304326

305327
describe('aria labelling', () => {

src/material/tabs/tab-group.spec.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@ import {By} from '@angular/platform-browser';
66
import {BrowserAnimationsModule, NoopAnimationsModule} from '@angular/platform-browser/animations';
77
import {CommonModule} from '@angular/common';
88
import {Observable} from 'rxjs';
9-
import {MatTab, MatTabGroup, MatTabHeaderPosition, MatTabsModule, MAT_TABS_CONFIG} from './index';
9+
import {
10+
MatTab,
11+
MatTabGroup,
12+
MatTabHeader,
13+
MatTabHeaderPosition,
14+
MatTabsModule,
15+
MAT_TABS_CONFIG
16+
} from './index';
1017

1118

1219
describe('MatTabGroup', () => {
@@ -298,6 +305,22 @@ describe('MatTabGroup', () => {
298305
expect(tabLabelNativeElements.every(el => el.classList.contains('mat-focus-indicator')))
299306
.toBe(true);
300307
});
308+
309+
it('should be able to programmatically focus a particular tab', () => {
310+
fixture.detectChanges();
311+
const tabGroup: MatTabGroup =
312+
fixture.debugElement.query(By.css('mat-tab-group')).componentInstance;
313+
const tabHeader: MatTabHeader =
314+
fixture.debugElement.query(By.css('mat-tab-header')).componentInstance;
315+
316+
expect(tabHeader.focusIndex).not.toBe(3);
317+
318+
tabGroup.focusTab(3);
319+
fixture.detectChanges();
320+
321+
expect(tabHeader.focusIndex).not.toBe(3);
322+
});
323+
301324
});
302325

303326
describe('aria labelling', () => {

src/material/tabs/tab-group.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,18 @@ export abstract class _MatTabGroupBase extends _MatTabGroupMixinBase implements
286286
}
287287
}
288288

289+
/**
290+
* Sets focus to a particular tab.
291+
* @param index Index of the tab to be focused.
292+
*/
293+
focusTab(index: number) {
294+
const header = this._tabHeader;
295+
296+
if (header) {
297+
header.focusIndex = index;
298+
}
299+
}
300+
289301
_focusChanged(index: number) {
290302
this.focusChange.emit(this._createChangeEvent(index));
291303
}

tools/public_api_guard/material/tabs.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export declare abstract class _MatTabGroupBase extends _MatTabGroupMixinBase imp
5858
_handleClick(tab: MatTab, tabHeader: MatTabGroupBaseHeader, index: number): void;
5959
_removeTabBodyWrapperHeight(): void;
6060
_setTabBodyWrapperHeight(tabHeight: number): void;
61+
focusTab(index: number): void;
6162
ngAfterContentChecked(): void;
6263
ngAfterContentInit(): void;
6364
ngOnDestroy(): void;

0 commit comments

Comments
 (0)