diff --git a/src/cdk/stepper/stepper.ts b/src/cdk/stepper/stepper.ts index 7d588386fa93..6d17ba3e120c 100644 --- a/src/cdk/stepper/stepper.ts +++ b/src/cdk/stepper/stepper.ts @@ -402,6 +402,16 @@ export class CdkStepper implements AfterContentInit, AfterViewInit, OnDestroy { if (!this._isValidIndex(this._selectedIndex)) { this._selectedIndex = 0; } + + // For linear step and selected index is greater than zero, + // set all the previous steps to interacted so that we can navigate to previous steps. + if (this.linear && this._selectedIndex > 0) { + const visitedSteps = this.steps.toArray().slice(0, this._selectedIndex); + + for (const step of visitedSteps) { + step._markAsInteracted(); + } + } } ngOnDestroy() { diff --git a/src/material/stepper/stepper.spec.ts b/src/material/stepper/stepper.spec.ts index feb4c497012c..2a09bff71419 100644 --- a/src/material/stepper/stepper.spec.ts +++ b/src/material/stepper/stepper.spec.ts @@ -912,6 +912,27 @@ describe('MatStepper', () => { }); }); + describe('linear stepper with form already filled and on to the last step', () => { + let fixture: ComponentFixture; + let stepper: MatStepper; + + beforeEach(() => { + fixture = createComponent(LinearMatVerticalStepperAppForAlreadyFilledForm); + fixture.detectChanges(); + stepper = fixture.debugElement.query(By.directive(MatStepper))!.componentInstance; + }); + + it('should navigate to previous steps', () => { + expect(stepper.selectedIndex).toBe(2); + + stepper.previous(); + expect(stepper.selectedIndex).toBe(1); + + stepper.previous(); + expect(stepper.selectedIndex).toBe(0); + }); + }); + describe('linear stepper with no `stepControl`', () => { let noStepControlFixture: ComponentFixture; beforeEach(() => { @@ -1984,6 +2005,61 @@ class SimplePreselectedMatHorizontalStepperApp { index = 0; } +@Component({ + template: ` + + +
+ Step one + +
+ + +
+
+
+ +
+ Step two + +
+ + +
+
+
+ +
+ Step two + +
+ + +
+
+
+ + Done + +
+ `, + imports: [ReactiveFormsModule, MatStepperModule], + standalone: false, +}) +class LinearMatVerticalStepperAppForAlreadyFilledForm { + selectedIndex = signal(2); + + oneGroup = new FormGroup({ + oneCtrl: new FormControl('test 1', Validators.required), + }); + twoGroup = new FormGroup({ + twoCtrl: new FormControl('test 2', Validators.required), + }); + threeGroup = new FormGroup({ + threeCtrl: new FormControl('test 3', Validators.required), + }); +} + @Component({ template: `