diff --git a/src/cdk/stepper/stepper.ts b/src/cdk/stepper/stepper.ts index 6d17ba3e120c..a2e765f12502 100644 --- a/src/cdk/stepper/stepper.ts +++ b/src/cdk/stepper/stepper.ts @@ -284,20 +284,21 @@ export class CdkStepper implements AfterContentInit, AfterViewInit, OnDestroy { return this._selectedIndex; } set selectedIndex(index: number) { - if (this.steps && this._steps) { + if (this._steps) { // Ensure that the index can't be out of bounds. if (!this._isValidIndex(index) && (typeof ngDevMode === 'undefined' || ngDevMode)) { throw Error('cdkStepper: Cannot assign out-of-bounds value to `selectedIndex`.'); } - this.selected?._markAsInteracted(); + if (this._selectedIndex !== index) { + this.selected?._markAsInteracted(); - if ( - this._selectedIndex !== index && - !this._anyControlsInvalidOrPending(index) && - (index >= this._selectedIndex || this.steps.toArray()[index].editable) - ) { - this._updateSelectedItemIndex(index); + if ( + !this._anyControlsInvalidOrPending(index) && + (index >= this._selectedIndex || this.steps.toArray()[index].editable) + ) { + this._updateSelectedItemIndex(index); + } } } else { this._selectedIndex = index; diff --git a/src/material/stepper/stepper.spec.ts b/src/material/stepper/stepper.spec.ts index 2a09bff71419..cb4059ae8bec 100644 --- a/src/material/stepper/stepper.spec.ts +++ b/src/material/stepper/stepper.spec.ts @@ -1213,7 +1213,7 @@ describe('MatStepper', () => { fixture.detectChanges(); expect(stepper.steps.map(step => step.interacted)).toEqual([true, true, false]); - stepper.next(); + stepper.previous(); fixture.detectChanges(); expect(stepper.steps.map(step => step.interacted)).toEqual([true, true, true]); }); @@ -1240,12 +1240,36 @@ describe('MatStepper', () => { fixture.detectChanges(); expect(interactedSteps).toEqual([0, 1]); - stepper.next(); + stepper.previous(); fixture.detectChanges(); expect(interactedSteps).toEqual([0, 1, 2]); subscription.unsubscribe(); }); + it('should not emit interacted event if selectedIndex does not change', () => { + const fixture = createComponent(SimpleMatHorizontalStepperApp); + fixture.detectChanges(); + + const stepper: MatStepper = fixture.debugElement.query( + By.directive(MatStepper), + ).componentInstance; + const interactedSteps: number[] = []; + const subscription = merge(...stepper.steps.map(step => step.interactedStream)).subscribe( + step => interactedSteps.push(stepper.steps.toArray().indexOf(step as MatStep)), + ); + + expect(interactedSteps).toEqual([]); + + stepper.next(); + fixture.detectChanges(); + expect(interactedSteps).toEqual([0]); + + stepper.selectedIndex = 1; + fixture.detectChanges(); + expect(interactedSteps).toEqual([0]); + subscription.unsubscribe(); + }); + it('should set a class on the host if the header is positioned at the bottom', () => { const fixture = createComponent(SimpleMatHorizontalStepperApp); fixture.detectChanges();