Skip to content

Commit 761b21f

Browse files
committed
fix(overlay): lazily create container
1 parent 14805fe commit 761b21f

File tree

10 files changed

+69
-61
lines changed

10 files changed

+69
-61
lines changed

src/components/dialog/dialog.spec.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ import {
1313
ChangeDetectorRef,
1414
} from '@angular/core';
1515
import {MdDialog} from './dialog';
16-
import {OVERLAY_PROVIDERS, OVERLAY_CONTAINER_TOKEN} from '@angular2-material/core/overlay/overlay';
16+
import {OVERLAY_PROVIDERS} from '@angular2-material/core/overlay/overlay';
17+
import {OverlayContainer} from '@angular2-material/core/overlay/overlay-container';
1718
import {MdDialogConfig} from './dialog-config';
1819
import {MdDialogRef} from './dialog-ref';
1920

@@ -31,10 +32,14 @@ describe('MdDialog', () => {
3132
addProviders([
3233
OVERLAY_PROVIDERS,
3334
MdDialog,
34-
{provide: OVERLAY_CONTAINER_TOKEN, useFactory: () => {
35-
overlayContainerElement = document.createElement('div');
36-
return overlayContainerElement;
37-
}}
35+
{provide: OverlayContainer, useFactory: () => {
36+
return {
37+
getContainerElement: () => {
38+
overlayContainerElement = document.createElement('div');
39+
return overlayContainerElement;
40+
}
41+
};
42+
}},
3843
]);
3944
});
4045

src/components/menu/menu-trigger.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export class MdMenuTrigger implements AfterViewInit, OnDestroy {
7171
}
7272

7373
destroyMenu(): void {
74-
this._overlayRef.dispose();
74+
if (this._overlayRef) { this._overlayRef.dispose(); }
7575
}
7676

7777
// set state rather than toggle to support triggers sharing a menu

src/components/tooltip/tooltip.spec.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,23 @@ import {Component, provide, DebugElement} from '@angular/core';
1212
import {By} from '@angular/platform-browser';
1313
import {MD_TOOLTIP_DIRECTIVES, TooltipPosition, MdTooltip} from
1414
'@angular2-material/tooltip/tooltip';
15-
import {OVERLAY_PROVIDERS, OVERLAY_CONTAINER_TOKEN} from '@angular2-material/core/overlay/overlay';
15+
import {OVERLAY_PROVIDERS} from '@angular2-material/core/overlay/overlay';
16+
import {OverlayContainer} from '@angular2-material/core/overlay/overlay-container';
1617

1718
describe('MdTooltip', () => {
1819
let builder: TestComponentBuilder;
1920
let overlayContainerElement: HTMLElement;
2021

2122
beforeEachProviders(() => [
2223
OVERLAY_PROVIDERS,
23-
provide(OVERLAY_CONTAINER_TOKEN, {
24-
useFactory: () => {
25-
overlayContainerElement = document.createElement('div');
26-
return overlayContainerElement;
27-
}
28-
})
24+
{provide: OverlayContainer, useFactory: () => {
25+
return {
26+
getContainerElement: () => {
27+
overlayContainerElement = document.createElement('div');
28+
return overlayContainerElement;
29+
}
30+
};
31+
}},
2932
]);
3033

3134
beforeEach(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {

src/core/core.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ export {
1717
export {DomPortalHost} from './portal/dom-portal-host';
1818

1919
// Overlay
20-
export {Overlay, OVERLAY_CONTAINER_TOKEN, OVERLAY_PROVIDERS} from './overlay/overlay';
20+
export {Overlay, OVERLAY_PROVIDERS} from './overlay/overlay';
21+
export {OverlayContainer} from './overlay/overlay-container';
2122
export {OverlayRef} from './overlay/overlay-ref';
2223
export {OverlayState} from './overlay/overlay-state';
2324
export {

src/core/overlay/overlay-container.ts

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
11

22

3-
/**
4-
* Create the overlay container element, which is simply a div
5-
* with the 'md-overlay-container' class on the document body.
6-
*/
7-
export function createOverlayContainer(): Element {
8-
let container = document.createElement('div');
9-
container.classList.add('md-overlay-container');
10-
document.body.appendChild(container);
11-
return container;
3+
export class OverlayContainer {
4+
private _containerElement: Element;
5+
6+
getContainerElement(): Element {
7+
if (!this._containerElement) { this._createContainer(); }
8+
return this._containerElement;
9+
}
10+
11+
/**
12+
* Create the overlay container element, which is simply a div
13+
* with the 'md-overlay-container' class on the document body.
14+
*/
15+
private _createContainer(): void {
16+
let container = document.createElement('div');
17+
container.classList.add('md-overlay-container');
18+
document.body.appendChild(container);
19+
this._containerElement = container;
20+
}
1221
}

src/core/overlay/overlay-directives.spec.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ import {
88
import {TestComponentBuilder, ComponentFixture} from '@angular/compiler/testing';
99
import {Component, ViewChild} from '@angular/core';
1010
import {ConnectedOverlayDirective, OverlayOrigin} from './overlay-directives';
11-
import {OVERLAY_CONTAINER_TOKEN, Overlay} from './overlay';
11+
import {Overlay} from './overlay';
12+
import {OverlayContainer} from './overlay-container';
1213
import {ViewportRuler} from './position/viewport-ruler';
1314
import {OverlayPositionBuilder} from './position/overlay-position-builder';
1415
import {ConnectedPositionStrategy} from './position/connected-position-strategy';
1516

16-
1717
describe('Overlay directives', () => {
1818
let builder: TestComponentBuilder;
1919
let overlayContainerElement: HTMLElement;
@@ -24,9 +24,13 @@ describe('Overlay directives', () => {
2424
Overlay,
2525
OverlayPositionBuilder,
2626
ViewportRuler,
27-
{provide: OVERLAY_CONTAINER_TOKEN, useFactory: () => {
28-
overlayContainerElement = document.createElement('div');
29-
return overlayContainerElement;
27+
{provide: OverlayContainer, useFactory: () => {
28+
return {
29+
getContainerElement: () => {
30+
overlayContainerElement = document.createElement('div');
31+
return overlayContainerElement;
32+
}
33+
};
3034
}},
3135
]);
3236
});

src/core/overlay/overlay.spec.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ import {
1212
} from '@angular/core';
1313
import {TemplatePortalDirective} from '../portal/portal-directives';
1414
import {TemplatePortal, ComponentPortal} from '../portal/portal';
15-
import {Overlay, OVERLAY_CONTAINER_TOKEN} from './overlay';
15+
import {Overlay} from './overlay';
16+
import {OverlayContainer} from './overlay-container';
1617
import {OverlayRef} from './overlay-ref';
1718
import {OverlayState} from './overlay-state';
1819
import {PositionStrategy} from './position/position-strategy';
@@ -32,9 +33,14 @@ describe('Overlay', () => {
3233
Overlay,
3334
OverlayPositionBuilder,
3435
ViewportRuler,
35-
{provide: OVERLAY_CONTAINER_TOKEN, useFactory: () => {
36-
overlayContainerElement = document.createElement('div');
37-
return overlayContainerElement;
36+
{provide: OverlayContainer, useFactory: () => {
37+
return {
38+
getContainerElement: () => {
39+
if (overlayContainerElement) { return overlayContainerElement; }
40+
overlayContainerElement = document.createElement('div');
41+
return overlayContainerElement;
42+
}
43+
};
3844
}}
3945
]);
4046
});

src/core/overlay/overlay.ts

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import {
22
ComponentResolver,
3-
OpaqueToken,
4-
Inject,
53
Injectable,
64
} from '@angular/core';
75
import {OverlayState} from './overlay-state';
@@ -10,10 +8,7 @@ import {OverlayRef} from './overlay-ref';
108

119
import {OverlayPositionBuilder} from './position/overlay-position-builder';
1210
import {ViewportRuler} from './position/viewport-ruler';
13-
14-
15-
/** Token used to inject the DOM element that serves as the overlay container. */
16-
export const OVERLAY_CONTAINER_TOKEN = new OpaqueToken('overlayContainer');
11+
import {OverlayContainer} from './overlay-container';
1712

1813
/** Next overlay unique ID. */
1914
let nextUniqueId = 0;
@@ -32,18 +27,9 @@ let defaultState = new OverlayState();
3227
*/
3328
@Injectable()
3429
export class Overlay {
35-
private _overlayContainerElement: HTMLElement;
36-
37-
constructor(
38-
@Inject(OVERLAY_CONTAINER_TOKEN) overlayContainerElement: any,
39-
private _componentResolver: ComponentResolver,
40-
private _positionBuilder: OverlayPositionBuilder) {
41-
42-
// We inject the container as `any` because the constructor signature cannot reference
43-
// browser globals (HTMLElement) on non-browser environments, since having a class decorator
44-
// causes TypeScript to preserve the constructor signature types.
45-
this._overlayContainerElement = overlayContainerElement;
46-
}
30+
constructor(private _overlayContainer: OverlayContainer,
31+
private _componentResolver: ComponentResolver,
32+
private _positionBuilder: OverlayPositionBuilder) {}
4733

4834
/**
4935
* Creates an overlay.
@@ -71,7 +57,7 @@ export class Overlay {
7157
pane.id = `md-overlay-${nextUniqueId++}`;
7258
pane.classList.add('md-overlay-pane');
7359

74-
this._overlayContainerElement.appendChild(pane);
60+
this._overlayContainer.getContainerElement().appendChild(pane);
7561

7662
return Promise.resolve(pane);
7763
}

src/demo-app/main.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,10 @@ import {bootstrap} from '@angular/platform-browser-dynamic';
22
import {HAMMER_GESTURE_CONFIG} from '@angular/platform-browser';
33
import {HTTP_PROVIDERS} from '@angular/http';
44
import {disableDeprecatedForms, provideForms} from '@angular/forms';
5-
6-
import {OVERLAY_CONTAINER_TOKEN} from '@angular2-material/core/overlay/overlay';
75
import {MdLiveAnnouncer} from '@angular2-material/core/a11y/live-announcer';
8-
import {createOverlayContainer} from '@angular2-material/core/overlay/overlay-container';
96
import {MdGestureConfig} from '@angular2-material/core/gestures/MdGestureConfig';
107
import {MdIconRegistry} from '@angular2-material/icon/icon-registry';
11-
8+
import {OverlayContainer} from '@angular2-material/core/overlay/overlay-container';
129
import {DemoApp} from './demo-app/demo-app';
1310
import {DEMO_APP_ROUTE_PROVIDER} from './demo-app/routes';
1411

@@ -17,8 +14,8 @@ bootstrap(DemoApp, [
1714
disableDeprecatedForms(),
1815
provideForms(),
1916
MdLiveAnnouncer,
20-
{provide: OVERLAY_CONTAINER_TOKEN, useValue: createOverlayContainer()},
2117
HTTP_PROVIDERS,
18+
OverlayContainer,
2219
MdIconRegistry,
2320
{provide: HAMMER_GESTURE_CONFIG, useClass: MdGestureConfig},
2421
]);

src/e2e-app/main.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,10 @@ import {HAMMER_GESTURE_CONFIG} from '@angular/platform-browser';
33
import {HTTP_PROVIDERS} from '@angular/http';
44
import {Renderer} from '@angular/core';
55
import {disableDeprecatedForms, provideForms} from '@angular/forms';
6-
7-
import {OVERLAY_CONTAINER_TOKEN} from '@angular2-material/core/overlay/overlay';
86
import {MdLiveAnnouncer} from '@angular2-material/core/a11y/live-announcer';
9-
import {createOverlayContainer} from '@angular2-material/core/overlay/overlay-container';
107
import {MdGestureConfig} from '@angular2-material/core/gestures/MdGestureConfig';
118
import {MdIconRegistry} from '@angular2-material/icon/icon-registry';
12-
9+
import {OverlayContainer} from '@angular2-material/core/overlay/overlay-container';
1310
import {E2EApp} from './e2e-app/e2e-app';
1411
import {E2E_APP_ROUTE_PROVIDER} from './e2e-app/routes';
1512

@@ -18,7 +15,7 @@ bootstrap(E2EApp, [
1815
disableDeprecatedForms(),
1916
provideForms(),
2017
MdLiveAnnouncer,
21-
{provide: OVERLAY_CONTAINER_TOKEN, useValue: createOverlayContainer()},
18+
OverlayContainer,
2219
HTTP_PROVIDERS,
2320
MdIconRegistry,
2421
Renderer,

0 commit comments

Comments
 (0)