@@ -29,7 +29,7 @@ import {
2929} from '@angular/core' ;
3030import { MatSnackBarConfig , _SnackBarContainer } from '@angular/material/snack-bar' ;
3131import { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations' ;
32- import { MDCSnackbarAdapter , MDCSnackbarFoundation } from '@material/snackbar' ;
32+ import { MDCSnackbarAdapter , MDCSnackbarFoundation , cssClasses } from '@material/snackbar' ;
3333import { Platform } from '@angular/cdk/platform' ;
3434import { Observable , Subject } from 'rxjs' ;
3535
@@ -98,10 +98,7 @@ export class MatSnackBarContainer
9898 addClass : ( className : string ) => this . _setClass ( className , true ) ,
9999 removeClass : ( className : string ) => this . _setClass ( className , false ) ,
100100 announce : ( ) => { } ,
101- notifyClosed : ( ) => {
102- this . _onExit . next ( ) ;
103- this . _mdcFoundation . destroy ( ) ;
104- } ,
101+ notifyClosed : ( ) => this . _finishExit ( ) ,
105102 notifyClosing : ( ) => { } ,
106103 notifyOpened : ( ) => this . _onEnter . next ( ) ,
107104 notifyOpening : ( ) => { } ,
@@ -184,16 +181,24 @@ export class MatSnackBarContainer
184181 }
185182
186183 exit ( ) : Observable < void > {
187- // It's common for snack bars to be opened by random outside calls like HTTP requests or
188- // errors. Run inside the NgZone to ensure that it functions correctly.
189- this . _ngZone . run ( ( ) => {
190- this . _exiting = true ;
191- this . _mdcFoundation . close ( ) ;
184+ const classList = this . _elementRef . nativeElement . classList ;
185+
186+ // MDC won't complete the closing sequence if it starts while opening hasn't finished.
187+ // If that's the case, destroy immediately to ensure that our stream emits as expected.
188+ if ( classList . contains ( cssClasses . OPENING ) || ! classList . contains ( cssClasses . OPEN ) ) {
189+ this . _finishExit ( ) ;
190+ } else {
191+ // It's common for snack bars to be opened by random outside calls like HTTP requests or
192+ // errors. Run inside the NgZone to ensure that it functions correctly.
193+ this . _ngZone . run ( ( ) => {
194+ this . _exiting = true ;
195+ this . _mdcFoundation . close ( ) ;
196+ } ) ;
197+ }
192198
193- // If the snack bar hasn't been announced by the time it exits it wouldn't have been open
194- // long enough to visually read it either, so clear the timeout for announcing.
195- clearTimeout ( this . _announceTimeoutId ) ;
196- } ) ;
199+ // If the snack bar hasn't been announced by the time it exits it wouldn't have been open
200+ // long enough to visually read it either, so clear the timeout for announcing.
201+ clearTimeout ( this . _announceTimeoutId ) ;
197202
198203 return this . _onExit ;
199204 }
@@ -236,6 +241,16 @@ export class MatSnackBarContainer
236241 }
237242 }
238243
244+ /** Finishes the exit sequence of the container. */
245+ private _finishExit ( ) {
246+ this . _onExit . next ( ) ;
247+ this . _onExit . complete ( ) ;
248+
249+ if ( this . _platform . isBrowser ) {
250+ this . _mdcFoundation . destroy ( ) ;
251+ }
252+ }
253+
239254 /**
240255 * Starts a timeout to move the snack bar content to the live region so screen readers will
241256 * announce it.
0 commit comments