Skip to content

Commit 5c2081c

Browse files
committed
fix(overlay): clear duplicate overlay container coming in from the server
When coming from a server-side-rendered page, we may end up in a situation where there are multiple overlay containers on the page with stale overlays in them. These changes clear all old overlay containers before creating a new one. Relates to #11817.
1 parent 98711d7 commit 5c2081c

File tree

2 files changed

+27
-4
lines changed

2 files changed

+27
-4
lines changed

src/cdk/overlay/overlay-container.spec.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,16 @@ describe('OverlayContainer', () => {
5252
expect(containerElement.classList.contains('commander-shepard'))
5353
.toBe(false, 'Expected the overlay container not to have class "commander-shepard"');
5454
});
55+
56+
it('should ensure that there is only one overlay container on the page', () => {
57+
const extraContainer = document.createElement('div');
58+
extraContainer.classList.add('cdk-overlay-container');
59+
document.body.appendChild(extraContainer);
60+
61+
overlayContainer.getContainerElement();
62+
63+
expect(document.querySelectorAll('.cdk-overlay-container').length).toBe(1);
64+
});
5565
});
5666

5767
/** Test-bed component that contains a TempatePortal and an ElementRef. */

src/cdk/overlay/overlay-container.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@ import {
2121
@Injectable({providedIn: 'root'})
2222
export class OverlayContainer implements OnDestroy {
2323
protected _containerElement: HTMLElement;
24+
protected _document: Document;
2425

25-
constructor(@Inject(DOCUMENT) protected _document: any) {}
26+
constructor(@Inject(DOCUMENT) document: any) {
27+
this._document = document;
28+
}
2629

2730
ngOnDestroy() {
2831
if (this._containerElement && this._containerElement.parentNode) {
@@ -37,7 +40,10 @@ export class OverlayContainer implements OnDestroy {
3740
* @returns the container element
3841
*/
3942
getContainerElement(): HTMLElement {
40-
if (!this._containerElement) { this._createContainer(); }
43+
if (!this._containerElement) {
44+
this._createContainer();
45+
}
46+
4147
return this._containerElement;
4248
}
4349

@@ -46,9 +52,16 @@ export class OverlayContainer implements OnDestroy {
4652
* with the 'cdk-overlay-container' class on the document body.
4753
*/
4854
protected _createContainer(): void {
49-
const container = this._document.createElement('div');
55+
const containerClass = 'cdk-overlay-container';
56+
const previousContainers = this._document.getElementsByClassName(containerClass);
5057

51-
container.classList.add('cdk-overlay-container');
58+
// Remove any old containers. This can happen when transitioning from the server to the client.
59+
for (let i = 0; i < previousContainers.length; i++) {
60+
previousContainers[i].parentNode!.removeChild(previousContainers[i]);
61+
}
62+
63+
const container = this._document.createElement('div');
64+
container.classList.add(containerClass);
5265
this._document.body.appendChild(container);
5366
this._containerElement = container;
5467
}

0 commit comments

Comments
 (0)