Skip to content

Commit 3a50c41

Browse files
authored
feat(cdk/stepper): allow for orientation to be changed (#21940)
Currently we have a limitation on the Material stepper that doesn't allow its orientation to be changed dynamically, because we have two different components for it. The CDK stepper doesn't have this limitation and people may end up extending it to implement their own steppers which support changing orientations. These changes add some logic to ensure that changing the orientation works as expected and to ensure that the orientation of the Material stepper doesn't change. Fixes #21874.
1 parent e9a446e commit 3a50c41

File tree

6 files changed

+40
-0
lines changed

6 files changed

+40
-0
lines changed

src/cdk/stepper/stepper.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,17 @@ export class CdkStepper implements AfterContentInit, AfterViewInit, OnDestroy {
332332
/** Used to track unique ID for each stepper component. */
333333
_groupId: number;
334334

335+
// Note that this isn't an `Input` so it doesn't bleed into the Material stepper.
336+
/** Orientation of the stepper. */
337+
get orientation(): StepperOrientation { return this._orientation; }
338+
set orientation(value: StepperOrientation) {
339+
this._updateOrientation(value);
340+
}
341+
342+
/**
343+
* @deprecated To be turned into a private property. Use `orientation` instead.
344+
* @breaking-change 13.0.0
345+
*/
335346
protected _orientation: StepperOrientation = 'horizontal';
336347

337348
constructor(
@@ -439,6 +450,16 @@ export class CdkStepper implements AfterContentInit, AfterViewInit, OnDestroy {
439450
this._getGuidelineLogic(step, isCurrentStep, state);
440451
}
441452

453+
/** Updates the stepper orientation. */
454+
protected _updateOrientation(value: StepperOrientation) {
455+
// This is a protected method so that `MatSteppter` can hook into it.
456+
this._orientation = value;
457+
458+
if (this._keyManager) {
459+
this._keyManager.withVerticalOrientation(value === 'vertical');
460+
}
461+
}
462+
442463
private _getDefaultIndicatorLogic(step: CdkStep, isCurrentStep: boolean): StepState {
443464
if (step._showError && step.hasError && !isCurrentStep) {
444465
return STEP_STATE.ERROR;

src/material/stepper/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ ng_module(
2424
] + glob(["**/*.html"]),
2525
module_name = "@angular/material/stepper",
2626
deps = [
27+
"//src:dev_mode_types",
2728
"//src/cdk/a11y",
2829
"//src/cdk/bidi",
2930
"//src/cdk/portal",

src/material/stepper/stepper.spec.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,14 @@ describe('MatStepper', () => {
395395
.every(element => element.classList.contains('mat-focus-indicator'))).toBe(true);
396396
});
397397

398+
it('should throw when trying to change the orientation of a stepper', () => {
399+
const stepperComponent: MatStepper = fixture.debugElement
400+
.query(By.css('mat-vertical-stepper'))!.componentInstance;
401+
402+
expect(() => stepperComponent.orientation = 'horizontal')
403+
.toThrowError('Updating the orientation of a Material stepper is not supported.');
404+
});
405+
398406
});
399407

400408
describe('basic stepper when attempting to set the selected step too early', () => {

src/material/stepper/stepper.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,12 @@ export class MatStepper extends CdkStepper implements AfterContentInit {
172172
});
173173
}
174174

175+
protected _updateOrientation() {
176+
if ((typeof ngDevMode === 'undefined' || ngDevMode)) {
177+
throw Error('Updating the orientation of a Material stepper is not supported.');
178+
}
179+
}
180+
175181
static ngAcceptInputType_editable: BooleanInput;
176182
static ngAcceptInputType_optional: BooleanInput;
177183
static ngAcceptInputType_completed: BooleanInput;

tools/public_api_guard/cdk/stepper.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ export declare class CdkStepper implements AfterContentInit, AfterViewInit, OnDe
5555
_steps: QueryList<CdkStep>;
5656
get linear(): boolean;
5757
set linear(value: boolean);
58+
get orientation(): StepperOrientation;
59+
set orientation(value: StepperOrientation);
5860
get selected(): CdkStep;
5961
set selected(step: CdkStep);
6062
get selectedIndex(): number;
@@ -69,6 +71,7 @@ export declare class CdkStepper implements AfterContentInit, AfterViewInit, OnDe
6971
_getStepLabelId(i: number): string;
7072
_onKeydown(event: KeyboardEvent): void;
7173
_stateChanged(): void;
74+
protected _updateOrientation(value: StepperOrientation): void;
7275
next(): void;
7376
ngAfterContentInit(): void;
7477
ngAfterViewInit(): void;

tools/public_api_guard/material/stepper.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export declare class MatStepper extends CdkStepper implements AfterContentInit {
7979
color: ThemePalette;
8080
disableRipple: boolean;
8181
readonly steps: QueryList<MatStep>;
82+
protected _updateOrientation(): void;
8283
ngAfterContentInit(): void;
8384
static ngAcceptInputType_completed: BooleanInput;
8485
static ngAcceptInputType_editable: BooleanInput;

0 commit comments

Comments
 (0)