@@ -10,6 +10,7 @@ import {FocusableOption, FocusMonitor, FocusOrigin} from '@angular/cdk/a11y';
1010import { ENTER , hasModifierKey , SPACE } from '@angular/cdk/keycodes' ;
1111import {
1212 AfterViewInit ,
13+ Attribute ,
1314 ChangeDetectionStrategy ,
1415 ChangeDetectorRef ,
1516 Component ,
@@ -23,6 +24,8 @@ import {
2324 ViewEncapsulation ,
2425} from '@angular/core' ;
2526import { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations' ;
27+ import { HasTabIndex , HasTabIndexCtor , mixinTabIndex } from '@angular/material/core' ;
28+ import { NumberInput } from '@angular/cdk/coercion' ;
2629import { EMPTY , merge , Subscription } from 'rxjs' ;
2730import { filter } from 'rxjs/operators' ;
2831import { MatAccordionTogglePosition } from './accordion-base' ;
@@ -34,6 +37,15 @@ import {
3437} from './expansion-panel' ;
3538
3639
40+ // Boilerplate for applying mixins to MatExpansionPanelHeader.
41+ /** @docs -private */
42+ abstract class MatExpansionPanelHeaderBase {
43+ abstract readonly disabled : boolean ;
44+ }
45+ const _MatExpansionPanelHeaderMixinBase :
46+ HasTabIndexCtor &
47+ typeof MatExpansionPanelHeaderBase = mixinTabIndex ( MatExpansionPanelHeaderBase ) ;
48+
3749/**
3850 * Header element of a `<mat-expansion-panel>`.
3951 */
@@ -43,14 +55,15 @@ import {
4355 templateUrl : 'expansion-panel-header.html' ,
4456 encapsulation : ViewEncapsulation . None ,
4557 changeDetection : ChangeDetectionStrategy . OnPush ,
58+ inputs : [ 'tabIndex' ] ,
4659 animations : [
4760 matExpansionAnimations . indicatorRotate ,
4861 ] ,
4962 host : {
5063 'class' : 'mat-expansion-panel-header mat-focus-indicator' ,
5164 'role' : 'button' ,
5265 '[attr.id]' : 'panel._headerId' ,
53- '[attr.tabindex]' : 'disabled ? -1 : 0 ' ,
66+ '[attr.tabindex]' : 'tabIndex ' ,
5467 '[attr.aria-controls]' : '_getPanelId()' ,
5568 '[attr.aria-expanded]' : '_isExpanded()' ,
5669 '[attr.aria-disabled]' : 'panel.disabled' ,
@@ -63,7 +76,8 @@ import {
6376 '(keydown)' : '_keydown($event)' ,
6477 } ,
6578} )
66- export class MatExpansionPanelHeader implements AfterViewInit , OnDestroy , FocusableOption {
79+ export class MatExpansionPanelHeader extends _MatExpansionPanelHeaderMixinBase implements
80+ AfterViewInit , OnDestroy , FocusableOption , HasTabIndex {
6781 private _parentChangeSubscription = Subscription . EMPTY ;
6882
6983 constructor (
@@ -73,11 +87,14 @@ export class MatExpansionPanelHeader implements AfterViewInit, OnDestroy, Focusa
7387 private _changeDetectorRef : ChangeDetectorRef ,
7488 @Inject ( MAT_EXPANSION_PANEL_DEFAULT_OPTIONS ) @Optional ( )
7589 defaultOptions ?: MatExpansionPanelDefaultOptions ,
76- @Optional ( ) @Inject ( ANIMATION_MODULE_TYPE ) public _animationMode ?: string ) {
90+ @Optional ( ) @Inject ( ANIMATION_MODULE_TYPE ) public _animationMode ?: string ,
91+ @Attribute ( 'tabindex' ) tabIndex ?: string ) {
92+ super ( ) ;
7793 const accordionHideToggleChange = panel . accordion ?
7894 panel . accordion . _stateChanges . pipe (
7995 filter ( changes => ! ! ( changes [ 'hideToggle' ] || changes [ 'togglePosition' ] ) ) ) :
8096 EMPTY ;
97+ this . tabIndex = parseInt ( tabIndex || '' ) || 0 ;
8198
8299 // Since the toggle state depends on an @Input on the panel, we
83100 // need to subscribe and trigger change detection manually.
@@ -210,6 +227,8 @@ export class MatExpansionPanelHeader implements AfterViewInit, OnDestroy, Focusa
210227 this . _parentChangeSubscription . unsubscribe ( ) ;
211228 this . _focusMonitor . stopMonitoring ( this . _element ) ;
212229 }
230+
231+ static ngAcceptInputType_tabIndex : NumberInput ;
213232}
214233
215234/**
0 commit comments