Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/cdk/stepper/public-api.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,3 +10,4 @@ export * from './stepper';
export * from './step-label';
export * from './stepper-button';
export * from './stepper-module';
export * from './step-header';
26 changes: 26 additions & 0 deletions src/cdk/stepper/step-header.ts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {Directive, ElementRef} from '@angular/core';
import {FocusableOption} from '@angular/cdk/a11y';


@Directive({
selector: '[cdkStepHeader]',
host: {
'role': 'tab',
},
})
export class CdkStepHeader implements FocusableOption {
constructor(protected _elementRef: ElementRef<HTMLElement>) {}

/** Focuses the step header. */
focus() {
this._elementRef.nativeElement.focus();
}
}
19 changes: 17 additions & 2 deletions src/cdk/stepper/stepper-module.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,11 +11,26 @@ import {CdkStepper, CdkStep} from './stepper';
import {CommonModule} from '@angular/common';
import {CdkStepLabel} from './step-label';
import {CdkStepperNext, CdkStepperPrevious} from './stepper-button';
import {CdkStepHeader} from './step-header';
import {BidiModule} from '@angular/cdk/bidi';

@NgModule({
imports: [BidiModule, CommonModule],
exports: [CdkStep, CdkStepper, CdkStepLabel, CdkStepperNext, CdkStepperPrevious],
declarations: [CdkStep, CdkStepper, CdkStepLabel, CdkStepperNext, CdkStepperPrevious]
exports: [
CdkStep,
CdkStepper,
CdkStepHeader,
CdkStepLabel,
CdkStepperNext,
CdkStepperPrevious,
],
declarations: [
CdkStep,
CdkStepper,
CdkStepHeader,
CdkStepLabel,
CdkStepperNext,
CdkStepperPrevious,
]
})
export class CdkStepperModule {}
14 changes: 11 additions & 3 deletions src/cdk/stepper/stepper.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -38,6 +38,7 @@ import {AbstractControl} from '@angular/forms';
import {CdkStepLabel} from './step-label';
import {Observable, Subject, of as obaservableOf} from 'rxjs';
import {startWith, takeUntil} from 'rxjs/operators';
import {CdkStepHeader} from './step-header';

/** Used to generate unique ID for each stepper component. */
let nextId = 0;
Expand DownExpand Up@@ -242,8 +243,12 @@ export class CdkStepper implements AfterViewInit, OnDestroy {
/** The list of step components that the stepper is holding. */
@ContentChildren(CdkStep) _steps: QueryList<CdkStep>;

/** The list of step headers of the steps in the stepper. */
_stepHeader: QueryList<FocusableOption>;
/**
* The list of step headers of the steps in the stepper.
* @deprecated Type to be changed to `QueryList<CdkStepHeader>`.
* @breaking-change 8.0.0
*/
@ContentChildren(CdkStepHeader) _stepHeader: QueryList<FocusableOption>;

/** Whether the validity of previous steps should be checked or not. */
@Input()
Expand DownExpand Up@@ -302,7 +307,10 @@ export class CdkStepper implements AfterViewInit, OnDestroy {
}

ngAfterViewInit() {
this._keyManager = new FocusKeyManager(this._stepHeader)
// Note that while the step headers are content children by default, any components that
// extend this one might have them as view chidren. We initialize the keyboard handling in
// AfterViewInit so we're guaranteed for both view and content children to be defined.
this._keyManager = new FocusKeyManager<FocusableOption>(this._stepHeader)
.withWrap()
.withVerticalOrientation(this._orientation === 'vertical');

Expand Down
18 changes: 8 additions & 10 deletions src/lib/stepper/step-header.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,7 +21,8 @@ import {Subscription} from 'rxjs';
import {MatStepLabel} from './step-label';
import {MatStepperIntl} from './stepper-intl';
import {MatStepperIconContext} from './stepper-icon';
import {StepState} from '@angular/cdk/stepper';
import {CdkStepHeader, StepState} from '@angular/cdk/stepper';


@Component({
moduleId: module.id,
Expand All@@ -35,7 +36,7 @@ import {StepState} from '@angular/cdk/stepper';
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MatStepHeader implements OnDestroy {
export class MatStepHeader extends CdkStepHeader implements OnDestroy {
private _intlSubscription: Subscription;

/** State of the given step. */
Expand DownExpand Up@@ -65,15 +66,16 @@ export class MatStepHeader implements OnDestroy {
constructor(
public _intl: MatStepperIntl,
private _focusMonitor: FocusMonitor,
private _element: ElementRef<HTMLElement>,
_elementRef: ElementRef<HTMLElement>,
changeDetectorRef: ChangeDetectorRef) {
_focusMonitor.monitor(_element, true);
super(_elementRef);
_focusMonitor.monitor(_elementRef, true);
this._intlSubscription = _intl.changes.subscribe(() => changeDetectorRef.markForCheck());
}

ngOnDestroy() {
this._intlSubscription.unsubscribe();
this._focusMonitor.stopMonitoring(this._element);
this._focusMonitor.stopMonitoring(this._elementRef);
}

/** Returns string label of given step if it is a text label. */
Expand All@@ -88,7 +90,7 @@ export class MatStepHeader implements OnDestroy {

/** Returns the host HTML element. */
_getHostElement() {
return this._element.nativeElement;
return this._elementRef.nativeElement;
}

/** Template context variables that are exposed to the `matStepperIcon` instances. */
Expand All@@ -99,8 +101,4 @@ export class MatStepHeader implements OnDestroy {
optional: this.optional
};
}

focus() {
this._getHostElement().focus();
}
}