fix(expansion-panel): emitting events twice on some browsers (#13600)

This commit is contained in:
Kristiyan Kostadinov
2018-10-19 17:16:57 +02:00
committed by Joey Perrott
parent e51de157e0
commit fa6e46da98
2 changed files with 20 additions and 13 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
<div class="mat-expansion-panel-content"
role="region"
[@bodyExpansion]="_getExpandedState()"
(@bodyExpansion.done)="_bodyAnimation($event)"
(@bodyExpansion.done)="_bodyAnimationDone.next($event)"
[attr.aria-labelledby]="_headerId"
[id]="id"
#body>
+19 -12
View File
@@ -35,7 +35,7 @@ import {
import {DOCUMENT} from '@angular/common';
import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';
import {Subject} from 'rxjs';
import {filter, startWith, take} from 'rxjs/operators';
import {filter, startWith, take, distinctUntilChanged} from 'rxjs/operators';
import {matExpansionAnimations} from './expansion-animations';
import {MatExpansionPanelContent} from './expansion-panel-content';
import {MAT_ACCORDION, MatAccordionBase} from './accordion-base';
@@ -119,6 +119,9 @@ export class MatExpansionPanel extends CdkAccordionItem implements AfterContentI
/** ID for the associated header element. Used for a11y labelling. */
_headerId = `mat-expansion-panel-header-${uniqueId++}`;
/** Stream of body animation done events. */
_bodyAnimationDone = new Subject<AnimationEvent>();
constructor(@Optional() @SkipSelf() @Inject(MAT_ACCORDION) accordion: MatAccordionBase,
_changeDetectorRef: ChangeDetectorRef,
_uniqueSelectionDispatcher: UniqueSelectionDispatcher,
@@ -129,6 +132,20 @@ export class MatExpansionPanel extends CdkAccordionItem implements AfterContentI
super(accordion, _changeDetectorRef, _uniqueSelectionDispatcher);
this.accordion = accordion;
this._document = _document;
// We need a Subject with distinctUntilChanged, because the `done` event
// fires twice on some browsers. See https://github.com/angular/angular/issues/24084
this._bodyAnimationDone.pipe(distinctUntilChanged((x, y) => {
return x.fromState === y.fromState && x.toState === y.toState;
})).subscribe(event => {
if (event.fromState !== 'void') {
if (event.toState === 'expanded') {
this.afterExpand.emit();
} else if (event.toState === 'collapsed') {
this.afterCollapse.emit();
}
}
});
}
/** Determines whether the expansion panel should have spacing between it and its siblings. */
@@ -166,20 +183,10 @@ export class MatExpansionPanel extends CdkAccordionItem implements AfterContentI
ngOnDestroy() {
super.ngOnDestroy();
this._bodyAnimationDone.complete();
this._inputChanges.complete();
}
_bodyAnimation(event: AnimationEvent) {
const {phaseName, toState, fromState} = event;
if (phaseName === 'done' && toState === 'expanded' && fromState !== 'void') {
this.afterExpand.emit();
}
if (phaseName === 'done' && toState === 'collapsed' && fromState !== 'void') {
this.afterCollapse.emit();
}
}
/** Checks whether the expansion panel's content contains the currently-focused element. */
_containsFocus(): boolean {
if (this._body && this._document) {