Skip to content

Commit cf11ff2

Browse files
crisbetoandrewseguin
authored andcommitted
fix(stepper): error when selectedIndex is pre-set (#8035)
Fixes an error that is thrown if the `selectedIndex` is set before the steps are initialized. Fixes #8031.
1 parent 3b50d3d commit cf11ff2

File tree

2 files changed

+42
-9
lines changed

2 files changed

+42
-9
lines changed

src/cdk/stepper/stepper.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -149,13 +149,17 @@ export class CdkStepper {
149149
@Input()
150150
get selectedIndex() { return this._selectedIndex; }
151151
set selectedIndex(index: number) {
152-
if (this._anyControlsInvalid(index)
153-
|| index < this._selectedIndex && !this._steps.toArray()[index].editable) {
154-
// remove focus from clicked step header if the step is not able to be selected
155-
this._stepHeader.toArray()[index].nativeElement.blur();
156-
} else if (this._selectedIndex != index) {
157-
this._emitStepperSelectionEvent(index);
158-
this._focusIndex = this._selectedIndex;
152+
if (this._steps) {
153+
if (this._anyControlsInvalid(index) || index < this._selectedIndex &&
154+
!this._steps.toArray()[index].editable) {
155+
// remove focus from clicked step header if the step is not able to be selected
156+
this._stepHeader.toArray()[index].nativeElement.blur();
157+
} else if (this._selectedIndex != index) {
158+
this._emitStepperSelectionEvent(index);
159+
this._focusIndex = this._selectedIndex;
160+
}
161+
} else {
162+
this._selectedIndex = this._focusIndex = index;
159163
}
160164
}
161165
private _selectedIndex: number = 0;
@@ -281,9 +285,12 @@ export class CdkStepper {
281285
}
282286

283287
private _anyControlsInvalid(index: number): boolean {
284-
this._steps.toArray()[this._selectedIndex].interacted = true;
288+
const steps = this._steps.toArray();
289+
290+
steps[this._selectedIndex].interacted = true;
291+
285292
if (this._linear && index >= 0) {
286-
return this._steps.toArray().slice(0, index).some(step => step.stepControl.invalid);
293+
return steps.slice(0, index).some(step => step.stepControl && step.stepControl.invalid);
287294
}
288295
return false;
289296
}

src/lib/stepper/stepper.spec.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ describe('MatHorizontalStepper', () => {
2121
imports: [MatStepperModule, NoopAnimationsModule, ReactiveFormsModule],
2222
declarations: [
2323
SimpleMatHorizontalStepperApp,
24+
SimplePreselectedMatHorizontalStepperApp,
2425
LinearMatHorizontalStepperApp
2526
],
2627
providers: [
@@ -168,6 +169,18 @@ describe('MatHorizontalStepper', () => {
168169
it('should be able to move to next step even when invalid if current step is optional', () => {
169170
assertOptionalStepValidity(testComponent, fixture);
170171
});
172+
173+
it('should not throw when there is a pre-defined selectedIndex', () => {
174+
fixture.destroy();
175+
176+
let preselectedFixture = TestBed.createComponent(SimplePreselectedMatHorizontalStepperApp);
177+
let debugElement = preselectedFixture.debugElement;
178+
179+
expect(() => preselectedFixture.detectChanges()).not.toThrow();
180+
181+
let stepHeaders = debugElement.queryAll(By.css('.mat-horizontal-stepper-header'));
182+
assertSelectionChangeOnHeaderClick(preselectedFixture, stepHeaders);
183+
});
171184
});
172185
});
173186

@@ -862,3 +875,16 @@ class LinearMatVerticalStepperApp {
862875
});
863876
}
864877
}
878+
879+
@Component({
880+
template: `
881+
<mat-horizontal-stepper [linear]="true" [selectedIndex]="index">
882+
<mat-step label="One"></mat-step>
883+
<mat-step label="Two"></mat-step>
884+
<mat-step label="Three"></mat-step>
885+
</mat-horizontal-stepper>
886+
`
887+
})
888+
class SimplePreselectedMatHorizontalStepperApp {
889+
index = 0;
890+
}

0 commit comments

Comments
 (0)