From b450db7c3bebd35486fc58ee1c20338bc181a009 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Fri, 25 Dec 2020 16:55:05 +0200 Subject: [PATCH] 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. --- .../mdc-tabs/tab-group.spec.ts | 24 +++++++++++++++++- src/material/tabs/tab-group.spec.ts | 25 ++++++++++++++++++- src/material/tabs/tab-group.ts | 12 +++++++++ tools/public_api_guard/material/tabs.d.ts | 1 + 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/material-experimental/mdc-tabs/tab-group.spec.ts b/src/material-experimental/mdc-tabs/tab-group.spec.ts index 2812bff57b55..ac60eb63e482 100644 --- a/src/material-experimental/mdc-tabs/tab-group.spec.ts +++ b/src/material-experimental/mdc-tabs/tab-group.spec.ts @@ -6,7 +6,14 @@ import {By} from '@angular/platform-browser'; import {BrowserAnimationsModule, NoopAnimationsModule} from '@angular/platform-browser/animations'; import {CommonModule} from '@angular/common'; import {Observable} from 'rxjs'; -import {MAT_TABS_CONFIG, MatTab, MatTabGroup, MatTabHeaderPosition, MatTabsModule} from './index'; +import { + MAT_TABS_CONFIG, + MatTab, + MatTabGroup, + MatTabHeaderPosition, + MatTabsModule, + MatTabHeader, +} from './index'; describe('MDC-based MatTabGroup', () => { @@ -300,6 +307,21 @@ describe('MDC-based MatTabGroup', () => { .toBe(true); }); + it('should be able to programmatically focus a particular tab', () => { + fixture.detectChanges(); + const tabGroup: MatTabGroup = + fixture.debugElement.query(By.css('mat-tab-group')).componentInstance; + const tabHeader: MatTabHeader = + fixture.debugElement.query(By.css('mat-tab-header')).componentInstance; + + expect(tabHeader.focusIndex).not.toBe(3); + + tabGroup.focusTab(3); + fixture.detectChanges(); + + expect(tabHeader.focusIndex).not.toBe(3); + }); + }); describe('aria labelling', () => { diff --git a/src/material/tabs/tab-group.spec.ts b/src/material/tabs/tab-group.spec.ts index e4cb95cd4667..11a25a038aee 100644 --- a/src/material/tabs/tab-group.spec.ts +++ b/src/material/tabs/tab-group.spec.ts @@ -6,7 +6,14 @@ import {By} from '@angular/platform-browser'; import {BrowserAnimationsModule, NoopAnimationsModule} from '@angular/platform-browser/animations'; import {CommonModule} from '@angular/common'; import {Observable} from 'rxjs'; -import {MatTab, MatTabGroup, MatTabHeaderPosition, MatTabsModule, MAT_TABS_CONFIG} from './index'; +import { + MatTab, + MatTabGroup, + MatTabHeader, + MatTabHeaderPosition, + MatTabsModule, + MAT_TABS_CONFIG +} from './index'; describe('MatTabGroup', () => { @@ -298,6 +305,22 @@ describe('MatTabGroup', () => { expect(tabLabelNativeElements.every(el => el.classList.contains('mat-focus-indicator'))) .toBe(true); }); + + it('should be able to programmatically focus a particular tab', () => { + fixture.detectChanges(); + const tabGroup: MatTabGroup = + fixture.debugElement.query(By.css('mat-tab-group')).componentInstance; + const tabHeader: MatTabHeader = + fixture.debugElement.query(By.css('mat-tab-header')).componentInstance; + + expect(tabHeader.focusIndex).not.toBe(3); + + tabGroup.focusTab(3); + fixture.detectChanges(); + + expect(tabHeader.focusIndex).not.toBe(3); + }); + }); describe('aria labelling', () => { diff --git a/src/material/tabs/tab-group.ts b/src/material/tabs/tab-group.ts index 500bd997d73a..f3c41110fbd7 100644 --- a/src/material/tabs/tab-group.ts +++ b/src/material/tabs/tab-group.ts @@ -286,6 +286,18 @@ export abstract class _MatTabGroupBase extends _MatTabGroupMixinBase implements } } + /** + * Sets focus to a particular tab. + * @param index Index of the tab to be focused. + */ + focusTab(index: number) { + const header = this._tabHeader; + + if (header) { + header.focusIndex = index; + } + } + _focusChanged(index: number) { this.focusChange.emit(this._createChangeEvent(index)); } diff --git a/tools/public_api_guard/material/tabs.d.ts b/tools/public_api_guard/material/tabs.d.ts index 262add0b7b99..88a7ca735b54 100644 --- a/tools/public_api_guard/material/tabs.d.ts +++ b/tools/public_api_guard/material/tabs.d.ts @@ -58,6 +58,7 @@ export declare abstract class _MatTabGroupBase extends _MatTabGroupMixinBase imp _handleClick(tab: MatTab, tabHeader: MatTabGroupBaseHeader, index: number): void; _removeTabBodyWrapperHeight(): void; _setTabBodyWrapperHeight(tabHeight: number): void; + focusTab(index: number): void; ngAfterContentChecked(): void; ngAfterContentInit(): void; ngOnDestroy(): void;