diff --git a/src/cdk/stepper/stepper.ts b/src/cdk/stepper/stepper.ts index 9cd5a2a7d673..8d6db9dc481b 100644 --- a/src/cdk/stepper/stepper.ts +++ b/src/cdk/stepper/stepper.ts @@ -149,13 +149,17 @@ export class CdkStepper { @Input() get selectedIndex() { return this._selectedIndex; } set selectedIndex(index: number) { - if (this._anyControlsInvalid(index) - || index < this._selectedIndex && !this._steps.toArray()[index].editable) { - // remove focus from clicked step header if the step is not able to be selected - this._stepHeader.toArray()[index].nativeElement.blur(); - } else if (this._selectedIndex != index) { - this._emitStepperSelectionEvent(index); - this._focusIndex = this._selectedIndex; + if (this._steps) { + if (this._anyControlsInvalid(index) || index < this._selectedIndex && + !this._steps.toArray()[index].editable) { + // remove focus from clicked step header if the step is not able to be selected + this._stepHeader.toArray()[index].nativeElement.blur(); + } else if (this._selectedIndex != index) { + this._emitStepperSelectionEvent(index); + this._focusIndex = this._selectedIndex; + } + } else { + this._selectedIndex = this._focusIndex = index; } } private _selectedIndex: number = 0; @@ -281,9 +285,12 @@ export class CdkStepper { } private _anyControlsInvalid(index: number): boolean { - this._steps.toArray()[this._selectedIndex].interacted = true; + const steps = this._steps.toArray(); + + steps[this._selectedIndex].interacted = true; + if (this._linear && index >= 0) { - return this._steps.toArray().slice(0, index).some(step => step.stepControl.invalid); + return steps.slice(0, index).some(step => step.stepControl && step.stepControl.invalid); } return false; } diff --git a/src/lib/stepper/stepper.spec.ts b/src/lib/stepper/stepper.spec.ts index 3e25aaf9465c..02a326cc8f77 100644 --- a/src/lib/stepper/stepper.spec.ts +++ b/src/lib/stepper/stepper.spec.ts @@ -21,6 +21,7 @@ describe('MatHorizontalStepper', () => { imports: [MatStepperModule, NoopAnimationsModule, ReactiveFormsModule], declarations: [ SimpleMatHorizontalStepperApp, + SimplePreselectedMatHorizontalStepperApp, LinearMatHorizontalStepperApp ], providers: [ @@ -168,6 +169,18 @@ describe('MatHorizontalStepper', () => { it('should be able to move to next step even when invalid if current step is optional', () => { assertOptionalStepValidity(testComponent, fixture); }); + + it('should not throw when there is a pre-defined selectedIndex', () => { + fixture.destroy(); + + let preselectedFixture = TestBed.createComponent(SimplePreselectedMatHorizontalStepperApp); + let debugElement = preselectedFixture.debugElement; + + expect(() => preselectedFixture.detectChanges()).not.toThrow(); + + let stepHeaders = debugElement.queryAll(By.css('.mat-horizontal-stepper-header')); + assertSelectionChangeOnHeaderClick(preselectedFixture, stepHeaders); + }); }); }); @@ -862,3 +875,16 @@ class LinearMatVerticalStepperApp { }); } } + +@Component({ + template: ` + + + + + + ` +}) +class SimplePreselectedMatHorizontalStepperApp { + index = 0; +}