Skip to content

Commit 4422c0f

Browse files
committed
fix(overlay): remove overlay container on destroy
1 parent 38b365c commit 4422c0f

File tree

3 files changed

+70
-11
lines changed

3 files changed

+70
-11
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import {async, inject, TestBed} from '@angular/core/testing';
2+
import {Component, NgModule, ViewChild, ViewContainerRef} from '@angular/core';
3+
import {PortalModule, TemplatePortalDirective} from '../portal/portal-directives';
4+
import {Overlay, OverlayContainer, OverlayModule} from './index';
5+
6+
describe('OverlayContainer', () => {
7+
let overlay: Overlay;
8+
let overlayContainer: OverlayContainer;
9+
10+
beforeEach(async(() => {
11+
TestBed.configureTestingModule({
12+
imports: [OverlayTestModule]
13+
}).compileComponents();
14+
}));
15+
16+
beforeEach(inject([Overlay, OverlayContainer], (o: Overlay, oc: OverlayContainer) => {
17+
overlay = o;
18+
overlayContainer = oc;
19+
}));
20+
21+
it('should remove the overlay container element from the DOM on destruction', () => {
22+
const fixture = TestBed.createComponent(TestComponentWithTemplatePortals);
23+
24+
const overlayRef = overlay.create();
25+
overlayRef.attach(fixture.componentInstance.templatePortal);
26+
fixture.detectChanges();
27+
28+
expect(document.body.querySelector('.cdk-overlay-container'))
29+
.not.toBeNull('Expected the overlay container to be in the DOM after opening an overlay');
30+
31+
// Manually call `ngOnDestroy` because there is no way to force Angular to destroy an
32+
// injectable in a unit test.
33+
overlayContainer.ngOnDestroy();
34+
35+
expect(document.body.querySelector('.cdk-overlay-container'))
36+
.toBeNull('Expected the overlay container *not* to be in the DOM after destruction');
37+
});
38+
});
39+
40+
/** Test-bed component that contains a TempatePortal and an ElementRef. */
41+
@Component({
42+
template: `<ng-template cdk-portal>Cake</ng-template>`,
43+
providers: [Overlay],
44+
})
45+
class TestComponentWithTemplatePortals {
46+
@ViewChild(TemplatePortalDirective) templatePortal: TemplatePortalDirective;
47+
48+
constructor(public viewContainerRef: ViewContainerRef) { }
49+
}
50+
51+
@NgModule({
52+
imports: [OverlayModule, PortalModule],
53+
declarations: [TestComponentWithTemplatePortals]
54+
})
55+
class OverlayTestModule { }

src/lib/core/overlay/overlay-container.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {Injectable, Optional, SkipSelf} from '@angular/core';
9+
import {Injectable, Optional, SkipSelf, OnDestroy} from '@angular/core';
1010

1111

1212
/**
1313
* The OverlayContainer is the container in which all overlays will load.
1414
* It should be provided in the root component to ensure it is properly shared.
1515
*/
1616
@Injectable()
17-
export class OverlayContainer {
17+
export class OverlayContainer implements OnDestroy {
1818
protected _containerElement: HTMLElement;
1919

2020
private _themeClass: string;
@@ -35,6 +35,12 @@ export class OverlayContainer {
3535
this._themeClass = value;
3636
}
3737

38+
ngOnDestroy() {
39+
if (this._containerElement && this._containerElement.parentNode) {
40+
this._containerElement.parentNode.removeChild(this._containerElement);
41+
}
42+
}
43+
3844
/**
3945
* This method returns the overlay container element. It will lazily
4046
* create the element the first time it is called to facilitate using

src/lib/core/overlay/overlay.spec.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
1-
import {inject, TestBed, async, ComponentFixture} from '@angular/core/testing';
2-
import {NgModule, Component, ViewChild, ViewContainerRef} from '@angular/core';
3-
import {TemplatePortalDirective, PortalModule} from '../portal/portal-directives';
4-
import {TemplatePortal, ComponentPortal} from '../portal/portal';
1+
import {async, ComponentFixture, inject, TestBed} from '@angular/core/testing';
2+
import {Component, NgModule, ViewChild, ViewContainerRef} from '@angular/core';
3+
import {PortalModule, TemplatePortalDirective} from '../portal/portal-directives';
4+
import {ComponentPortal, TemplatePortal} from '../portal/portal';
55
import {
6+
Overlay,
7+
OverlayContainer,
68
OverlayModule,
79
OverlayRef,
810
OverlayState,
9-
OverlayContainer,
10-
Overlay,
1111
PositionStrategy,
12-
ViewportRuler,
13-
ScrollStrategy,
14-
ScrollDispatcher,
12+
ScrollStrategy
1513
} from './index';
1614

1715

0 commit comments

Comments
 (0)