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 Jan 14, 2025
1 parent f9a9db6 commit cc13101
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 0 deletions.
11 changes: 11 additions & 0 deletions src/cdk/stepper/stepper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,17 @@ 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) {
this.steps
.toArray()
.slice(0, this._selectedIndex)
.map(step => {
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 @@ -917,6 +917,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 @@ -1989,6 +2010,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 cc13101

Please sign in to comment.