diff --git a/src/lib/snack-bar/snack-bar.spec.ts b/src/lib/snack-bar/snack-bar.spec.ts index 80ccca669d8..951f7592acc 100644 --- a/src/lib/snack-bar/snack-bar.spec.ts +++ b/src/lib/snack-bar/snack-bar.spec.ts @@ -452,6 +452,18 @@ describe('MatSnackBar', () => { .toContain('custom-class', 'Expected class applied through the defaults to be applied.'); })); + it('should dismiss the open snack bar on destroy', fakeAsync(() => { + snackBar.open(simpleMessage); + viewContainerFixture.detectChanges(); + expect(overlayContainerElement.childElementCount).toBeGreaterThan(0); + + snackBar.ngOnDestroy(); + viewContainerFixture.detectChanges(); + flush(); + + expect(overlayContainerElement.childElementCount).toBe(0); + })); + describe('with custom component', () => { it('should open a custom component', () => { const snackBarRef = snackBar.openFromComponent(BurritosNotification); @@ -603,6 +615,18 @@ describe('MatSnackBar with parent MatSnackBar', () => { expect(overlayContainerElement.textContent) .toContain('Taco', 'Expected child snackbar msg to be dismissed by opening from parent'); })); + + it('should not dismiss parent snack bar if child is destroyed', fakeAsync(() => { + parentSnackBar.open('Pizza'); + fixture.detectChanges(); + expect(overlayContainerElement.childElementCount).toBeGreaterThan(0); + + childSnackBar.ngOnDestroy(); + fixture.detectChanges(); + flush(); + + expect(overlayContainerElement.childElementCount).toBeGreaterThan(0); + })); }); describe('MatSnackBar Positioning', () => { diff --git a/src/lib/snack-bar/snack-bar.ts b/src/lib/snack-bar/snack-bar.ts index 425e46ef2e3..0492ce702ef 100644 --- a/src/lib/snack-bar/snack-bar.ts +++ b/src/lib/snack-bar/snack-bar.ts @@ -20,6 +20,7 @@ import { Optional, SkipSelf, TemplateRef, + OnDestroy, } from '@angular/core'; import {take, takeUntil} from 'rxjs/operators'; import {SimpleSnackBar} from './simple-snack-bar'; @@ -45,7 +46,7 @@ export function MAT_SNACK_BAR_DEFAULT_OPTIONS_FACTORY(): MatSnackBarConfig { * Service to dispatch Material Design snack bar messages. */ @Injectable({providedIn: MatSnackBarModule}) -export class MatSnackBar { +export class MatSnackBar implements OnDestroy { /** * Reference to the current snack bar in the view *at this level* (in the Angular injector tree). * If there is a parent snack-bar service, all operations should delegate to that parent @@ -129,6 +130,13 @@ export class MatSnackBar { } } + ngOnDestroy() { + // Only dismiss the snack bar at the current level on destroy. + if (this._snackBarRefAtThisLevel) { + this._snackBarRefAtThisLevel.dismiss(); + } + } + /** * Attaches the snack bar container component to the overlay. */