fix(overlay): remove overlay container on destroy (#5378)

This commit is contained in:
Jeremy Elbourn
2017-08-22 14:08:45 -07:00
committed by Kara
parent 363562f3e6
commit 154bb55689
2 changed files with 71 additions and 2 deletions
+8 -2
View File
@@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Injectable, Optional, SkipSelf} from '@angular/core';
import {Injectable, Optional, SkipSelf, OnDestroy} from '@angular/core';
/**
@@ -14,7 +14,7 @@ import {Injectable, Optional, SkipSelf} from '@angular/core';
* It should be provided in the root component to ensure it is properly shared.
*/
@Injectable()
export class OverlayContainer {
export class OverlayContainer implements OnDestroy {
protected _containerElement: HTMLElement;
private _themeClass: string;
@@ -37,6 +37,12 @@ export class OverlayContainer {
this._themeClass = value;
}
ngOnDestroy() {
if (this._containerElement && this._containerElement.parentNode) {
this._containerElement.parentNode.removeChild(this._containerElement);
}
}
/**
* This method returns the overlay container element. It will lazily
* create the element the first time it is called to facilitate using
@@ -0,0 +1,63 @@
import {async, inject, TestBed} from '@angular/core/testing';
import {Component, NgModule, ViewChild, ViewContainerRef} from '@angular/core';
import {PortalModule, TemplatePortalDirective} from '../portal/portal-directives';
import {Overlay, OverlayContainer, OverlayModule} from './index';
describe('OverlayContainer', () => {
let overlay: Overlay;
let overlayContainer: OverlayContainer;
beforeAll(() => {
// Remove any stale overlay containers from previous tests that didn't clean up correctly.
const staleContainers = document.querySelectorAll('.cdk-overlay-container');
for (let i = staleContainers.length - 1; i >= 0; i--) {
staleContainers[i].parentNode!.removeChild(staleContainers[i]);
}
});
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [OverlayTestModule]
}).compileComponents();
}));
beforeEach(inject([Overlay, OverlayContainer], (o: Overlay, oc: OverlayContainer) => {
overlay = o;
overlayContainer = oc;
}));
it('should remove the overlay container element from the DOM on destruction', () => {
const fixture = TestBed.createComponent(TestComponentWithTemplatePortals);
const overlayRef = overlay.create();
overlayRef.attach(fixture.componentInstance.templatePortal);
fixture.detectChanges();
expect(document.querySelectorAll('.cdk-overlay-container'))
.not.toBeNull('Expected the overlay container to be in the DOM after opening an overlay');
// Manually call `ngOnDestroy` because there is no way to force Angular to destroy an
// injectable in a unit test.
overlayContainer.ngOnDestroy();
expect(document.querySelector('.cdk-overlay-container'))
.toBeNull('Expected the overlay container *not* to be in the DOM after destruction');
});
});
/** Test-bed component that contains a TempatePortal and an ElementRef. */
@Component({
template: `<ng-template cdk-portal>Cake</ng-template>`,
providers: [Overlay],
})
class TestComponentWithTemplatePortals {
@ViewChild(TemplatePortalDirective) templatePortal: TemplatePortalDirective;
constructor(public viewContainerRef: ViewContainerRef) { }
}
@NgModule({
imports: [OverlayModule, PortalModule],
declarations: [TestComponentWithTemplatePortals]
})
class OverlayTestModule { }