diff --git a/src/lib/stepper/stepper-horizontal.html b/src/lib/stepper/stepper-horizontal.html index 8e2b442c0c3f..991d96f05b84 100644 --- a/src/lib/stepper/stepper-horizontal.html +++ b/src/lib/stepper/stepper-horizontal.html @@ -28,7 +28,7 @@
diff --git a/src/lib/stepper/stepper-vertical.html b/src/lib/stepper/stepper-vertical.html index 3ad0627b04e0..3c2ad34f172d 100644 --- a/src/lib/stepper/stepper-vertical.html +++ b/src/lib/stepper/stepper-vertical.html @@ -23,7 +23,7 @@
diff --git a/src/lib/stepper/stepper.ts b/src/lib/stepper/stepper.ts index 00f37d2b13e2..2dab42ab0628 100644 --- a/src/lib/stepper/stepper.ts +++ b/src/lib/stepper/stepper.ts @@ -39,7 +39,8 @@ import { import {FormControl, FormGroupDirective, NgForm} from '@angular/forms'; import {DOCUMENT} from '@angular/common'; import {ErrorStateMatcher} from '@angular/material/core'; -import {takeUntil} from 'rxjs/operators'; +import {Subject} from 'rxjs'; +import {takeUntil, distinctUntilChanged} from 'rxjs/operators'; import {MatStepHeader} from './step-header'; import {MatStepLabel} from './step-label'; @@ -102,18 +103,26 @@ export class MatStepper extends _CdkStepper implements AfterContentInit { /** Consumer-specified template-refs to be used to override the header icons. */ _iconOverrides: {[key: string]: TemplateRef} = {}; + /** Stream of animation `done` events when the body expands/collapses. */ + _animationDone = new Subject(); + ngAfterContentInit() { - const icons = this._icons.toArray(); - icons.forEach(({name, templateRef}) => this._iconOverrides[name] = templateRef); + this._icons.forEach(({name, templateRef}) => this._iconOverrides[name] = templateRef); // Mark the component for change detection whenever the content children query changes this._steps.changes.pipe(takeUntil(this._destroyed)).subscribe(() => this._stateChanged()); - } - _animationDone(event: AnimationEvent) { - if ((event.toState as StepContentPositionState) === 'current') { - this.animationDone.emit(); - } + this._animationDone.pipe( + // This needs a `distinctUntilChanged` in order to avoid emitting the same event twice due + // to a bug in animations where the `.done` callback gets invoked twice on some browsers. + // See https://github.com/angular/angular/issues/24084 + distinctUntilChanged((x, y) => x.fromState === y.fromState && x.toState === y.toState), + takeUntil(this._destroyed) + ).subscribe(event => { + if ((event.toState as StepContentPositionState) === 'current') { + this.animationDone.emit(); + } + }); } }