Skip to content

Commit

Permalink
fix(cdk/stepper): Linear stepper after initialization navigating to p…
Browse files Browse the repository at this point in the history
…revious step issue

Set the step as interacted if its linear step and is not the first step.

#15449
  • Loading branch information
mistrykaran91 committed Feb 12, 2025
1 parent ed64716 commit 17f4416
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/cdk/stepper/stepper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
76 changes: 76 additions & 0 deletions src/material/stepper/stepper.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -912,6 +912,27 @@ describe('MatStepper', () => {
});
});

describe('linear stepper with form already filled and on to the last step', () => {
let fixture: ComponentFixture<LinearMatVerticalStepperAppForAlreadyFilledForm>;
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<SimpleStepperWithoutStepControl>;
beforeEach(() => {
Expand Down Expand Up @@ -1984,6 +2005,61 @@ class SimplePreselectedMatHorizontalStepperApp {
index = 0;
}

@Component({
template: `
<mat-stepper linear [selectedIndex]="selectedIndex()">
<mat-step [stepControl]="oneGroup">
<form [formGroup]="oneGroup">
<ng-template matStepLabel>Step one</ng-template>
<input formControlName="oneCtrl" required>
<div>
<button matStepperPrevious>Back</button>
<button matStepperNext>Next</button>
</div>
</form>
</mat-step>
<mat-step [stepControl]="twoGroup">
<form [formGroup]="twoGroup">
<ng-template matStepLabel>Step two</ng-template>
<input formControlName="twoCtrl" required>
<div>
<button matStepperPrevious>Back</button>
<button matStepperNext>Next</button>
</div>
</form>
</mat-step>
<mat-step [stepControl]="threeGroup" optional>
<form [formGroup]="threeGroup">
<ng-template matStepLabel>Step two</ng-template>
<input formControlName="threeCtrl">
<div>
<button matStepperPrevious>Back</button>
<button matStepperNext>Next</button>
</div>
</form>
</mat-step>
<mat-step>
Done
</mat-step>
</mat-stepper>
`,
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: `
<mat-stepper linear>
Expand Down

0 comments on commit 17f4416

Please sign in to comment.