@@ -37,7 +37,15 @@ import {
3737 ViewEncapsulation ,
3838} from '@angular/core' ;
3939import { fromEvent , merge , Observable , Subject } from 'rxjs' ;
40- import { debounceTime , filter , map , startWith , take , takeUntil } from 'rxjs/operators' ;
40+ import {
41+ debounceTime ,
42+ filter ,
43+ map ,
44+ startWith ,
45+ take ,
46+ takeUntil ,
47+ distinctUntilChanged ,
48+ } from 'rxjs/operators' ;
4149import { matDrawerAnimations } from './drawer-animations' ;
4250import { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations' ;
4351
@@ -108,8 +116,8 @@ export class MatDrawerContent extends CdkScrollable implements AfterContentInit
108116 host : {
109117 'class' : 'mat-drawer' ,
110118 '[@transform]' : '_animationState' ,
111- '(@transform.start)' : '_onAnimationStart ($event)' ,
112- '(@transform.done)' : '_onAnimationEnd ($event)' ,
119+ '(@transform.start)' : '_animationStarted.next ($event)' ,
120+ '(@transform.done)' : '_animationEnd.next ($event)' ,
113121 // must prevent the browser from aligning text based on value
114122 '[attr.align]' : 'null' ,
115123 '[class.mat-drawer-end]' : 'position === "end"' ,
@@ -166,7 +174,10 @@ export class MatDrawer implements AfterContentInit, AfterContentChecked, OnDestr
166174 private _openedVia : FocusOrigin | null ;
167175
168176 /** Emits whenever the drawer has started animating. */
169- _animationStarted = new EventEmitter < AnimationEvent > ( ) ;
177+ _animationStarted = new Subject < AnimationEvent > ( ) ;
178+
179+ /** Emits whenever the drawer is done animating. */
180+ _animationEnd = new Subject < AnimationEvent > ( ) ;
170181
171182 /** Current state of the sidenav animation. */
172183 _animationState : 'open-instant' | 'open' | 'void' = 'void' ;
@@ -255,6 +266,19 @@ export class MatDrawer implements AfterContentInit, AfterContentChecked, OnDestr
255266 event . stopPropagation ( ) ;
256267 } ) ) ;
257268 } ) ;
269+
270+ // We need a Subject with distinctUntilChanged, because the `done` event
271+ // fires twice on some browsers. See https://github.com/angular/angular/issues/24084
272+ this . _animationEnd . pipe ( distinctUntilChanged ( ( x , y ) => {
273+ return x . fromState === y . fromState && x . toState === y . toState ;
274+ } ) ) . subscribe ( ( event : AnimationEvent ) => {
275+ const { fromState, toState} = event ;
276+
277+ if ( ( toState . indexOf ( 'open' ) === 0 && fromState === 'void' ) ||
278+ ( toState === 'void' && fromState . indexOf ( 'open' ) === 0 ) ) {
279+ this . openedChange . emit ( this . _opened ) ;
280+ }
281+ } ) ;
258282 }
259283
260284 /** Traps focus inside the drawer. */
@@ -314,6 +338,9 @@ export class MatDrawer implements AfterContentInit, AfterContentChecked, OnDestr
314338 if ( this . _focusTrap ) {
315339 this . _focusTrap . destroy ( ) ;
316340 }
341+
342+ this . _animationStarted . complete ( ) ;
343+ this . _animationEnd . complete ( ) ;
317344 }
318345
319346 /**
@@ -367,19 +394,6 @@ export class MatDrawer implements AfterContentInit, AfterContentChecked, OnDestr
367394 } ) ;
368395 }
369396
370- _onAnimationStart ( event : AnimationEvent ) {
371- this . _animationStarted . emit ( event ) ;
372- }
373-
374- _onAnimationEnd ( event : AnimationEvent ) {
375- const { fromState, toState} = event ;
376-
377- if ( ( toState . indexOf ( 'open' ) === 0 && fromState === 'void' ) ||
378- ( toState === 'void' && fromState . indexOf ( 'open' ) === 0 ) ) {
379- this . openedChange . emit ( this . _opened ) ;
380- }
381- }
382-
383397 get _width ( ) : number {
384398 return this . _elementRef . nativeElement ? ( this . _elementRef . nativeElement . offsetWidth || 0 ) : 0 ;
385399 }
0 commit comments