Skip to content

Commit 517ea57

Browse files
crisbetojelbourn
authored andcommitted
fix(stepper): unable to skip optional steps in linear stepper (#9245)
Fixes users not being allowed to skip optional invalid steps inside of a linear stepper. Fixes #9239.
1 parent c3ec94d commit 517ea57

File tree

2 files changed

+10
-18
lines changed

2 files changed

+10
-18
lines changed

src/cdk/stepper/stepper.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,8 @@ export class CdkStepper implements OnDestroy {
304304
if (this._linear && index >= 0) {
305305
return steps.slice(0, index).some(step => {
306306
const control = step.stepControl;
307-
return control ? (control.invalid || control.pending) : !step.completed;
307+
const isIncomplete = control ? (control.invalid || control.pending) : !step.completed;
308+
return isIncomplete && !step.optional;
308309
});
309310
}
310311

src/lib/stepper/stepper.spec.ts

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -780,24 +780,26 @@ function assertEditableStepChange(fixture: ComponentFixture<any>) {
780780
}
781781

782782
/**
783-
* Asserts that it is possible to skip an optional step in linear stepper if there is no input
784-
* or the input is valid.
783+
* Asserts that it is possible to skip an optional step in linear
784+
* stepper if there is no input or the input is invalid.
785785
*/
786786
function assertOptionalStepValidity(testComponent:
787787
LinearMatHorizontalStepperApp | LinearMatVerticalStepperApp,
788788
fixture: ComponentFixture<any>) {
789-
let stepperComponent = fixture.debugElement.query(By.directive(MatStepper)).componentInstance;
789+
const stepperComponent: MatStepper = fixture.debugElement
790+
.query(By.directive(MatStepper)).componentInstance;
790791

791792
testComponent.oneGroup.get('oneCtrl')!.setValue('input');
792793
testComponent.twoGroup.get('twoCtrl')!.setValue('input');
793794
testComponent.validationTrigger.next();
794795
stepperComponent.selectedIndex = 2;
795796
fixture.detectChanges();
796797

798+
expect(stepperComponent._steps.toArray()[2].optional).toBe(true);
797799
expect(stepperComponent.selectedIndex).toBe(2);
798800
expect(testComponent.threeGroup.get('threeCtrl')!.valid).toBe(true);
799801

800-
let nextButtonNativeEl = fixture.debugElement
802+
const nextButtonNativeEl = fixture.debugElement
801803
.queryAll(By.directive(MatStepperNext))[2].nativeElement;
802804
nextButtonNativeEl.click();
803805
fixture.detectChanges();
@@ -812,15 +814,7 @@ function assertOptionalStepValidity(testComponent:
812814

813815
expect(testComponent.threeGroup.get('threeCtrl')!.valid).toBe(false);
814816
expect(stepperComponent.selectedIndex)
815-
.toBe(2, 'Expected selectedIndex to remain unchanged when optional step input is invalid.');
816-
817-
testComponent.threeGroup.get('threeCtrl')!.setValue('valid');
818-
nextButtonNativeEl.click();
819-
fixture.detectChanges();
820-
821-
expect(testComponent.threeGroup.get('threeCtrl')!.valid).toBe(true);
822-
expect(stepperComponent.selectedIndex)
823-
.toBe(3, 'Expected selectedIndex to change when optional step input is valid.');
817+
.toBe(3, 'Expected selectedIndex to change when optional step input is invalid.');
824818
}
825819

826820
/** Asserts that step header set the correct icon depending on the state of step. */
@@ -841,10 +835,7 @@ function assertCorrectStepIcon(fixture: ComponentFixture<any>,
841835
function asyncValidator(minLength: number, validationTrigger: Observable<any>): AsyncValidatorFn {
842836
return (control: AbstractControl): Observable<ValidationErrors | null> => {
843837
return validationTrigger.pipe(
844-
map(() => {
845-
const success = control.value && control.value.length >= minLength;
846-
return success ? null : { 'asyncValidation': {}};
847-
}),
838+
map(() => control.value && control.value.length >= minLength ? null : {asyncValidation: {}}),
848839
take(1)
849840
);
850841
};

0 commit comments

Comments
 (0)