Skip to content

Commit 77208a9

Browse files
committed
fix(overlay): Render the templates before placing them in the overlay.
This fixes positioning issues when rendering templates which contain embedded templates. The templates need to be rendered in order to properly determine width which can then determine placement.
1 parent a02ed5a commit 77208a9

File tree

5 files changed

+39
-2
lines changed

5 files changed

+39
-2
lines changed

src/demo-app/overlay/overlay-demo.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
Pasta 3
1111
</button>
1212

13+
<button cdk-overlay-origin #tortelliniOrigin="cdkOverlayOrigin" (click)="openTortelliniPanel()">
14+
Pasta 4
15+
</button>
16+
1317

1418
<button cdk-overlay-origin #trigger="cdkOverlayOrigin" (click)="isMenuOpen = !isMenuOpen">
1519
Open menu
@@ -27,4 +31,8 @@
2731
<p class="demo-fusilli"> Fusilli </p>
2832
</template>
2933

34+
<template cdk-portal #tortelliniTemplate="cdkPortal">
35+
<ul class="demo-tortellini"><li *ngFor="let filling of tortelliniFillings">{{filling}}</li></ul>
36+
</template>
37+
3038
<button (click)="openPanelWithBackdrop()">Backdrop panel</button>

src/demo-app/overlay/overlay-demo.scss

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,12 @@
1818
background-color: rebeccapurple;
1919
opacity: 0.5;
2020
}
21+
22+
.demo-tortellini {
23+
margin: 0;
24+
padding: 10px;
25+
border: 1px solid black;
26+
color: white;
27+
background-color: orangered;
28+
opacity: 0.5;
29+
}

src/demo-app/overlay/overlay-demo.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,12 @@ import {
2626
export class OverlayDemo {
2727
nextPosition: number = 0;
2828
isMenuOpen: boolean = false;
29+
tortelliniFillings = ['cheese and spinach', 'mushroom and broccoli'];
2930

3031
@ViewChildren(TemplatePortalDirective) templatePortals: QueryList<Portal<any>>;
3132
@ViewChild(OverlayOrigin) _overlayOrigin: OverlayOrigin;
33+
@ViewChild('tortelliniOrigin') tortelliniOrigin: OverlayOrigin;
34+
@ViewChild('tortelliniTemplate') tortelliniTemplate: TemplatePortalDirective;
3235

3336
constructor(public overlay: Overlay, public viewContainerRef: ViewContainerRef) { }
3437

@@ -75,6 +78,21 @@ export class OverlayDemo {
7578
overlayRef.attach(new ComponentPortal(SpagettiPanel, this.viewContainerRef));
7679
}
7780

81+
openTortelliniPanel() {
82+
let strategy = this.overlay.position()
83+
.connectedTo(
84+
this.tortelliniOrigin.elementRef,
85+
{originX: 'start', originY: 'bottom'},
86+
{overlayX: 'end', overlayY: 'top'} );
87+
88+
let config = new OverlayState();
89+
config.positionStrategy = strategy;
90+
91+
let overlayRef = this.overlay.create(config);
92+
93+
overlayRef.attach(this.tortelliniTemplate);
94+
}
95+
7896
openPanelWithBackdrop() {
7997
let config = new OverlayState();
8098

src/lib/core/portal/dom-portal-host.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,12 @@ export class DomPortalHost extends BasePortalHost {
6464
attachTemplatePortal(portal: TemplatePortal): Map<string, any> {
6565
let viewContainer = portal.viewContainerRef;
6666
let viewRef = viewContainer.createEmbeddedView(portal.templateRef);
67+
viewRef.detectChanges();
6768

6869
// The method `createEmbeddedView` will add the view as a child of the viewContainer.
6970
// But for the DomPortalHost the view can be added everywhere in the DOM (e.g Overlay Container)
7071
// To move the view to the specified host element. We just re-append the existing root nodes.
7172
viewRef.rootNodes.forEach(rootNode => this._hostDomElement.appendChild(rootNode));
72-
7373
this.setDisposeFn((() => {
7474
let index = viewContainer.indexOf(viewRef);
7575
if (index !== -1) {

src/lib/core/portal/portal-directives.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,9 @@ export class PortalHostDirective extends BasePortalHost implements OnDestroy {
104104
attachTemplatePortal(portal: TemplatePortal): Map<string, any> {
105105
portal.setAttachedHost(this);
106106

107-
this._viewContainerRef.createEmbeddedView(portal.templateRef);
107+
const viewRef = this._viewContainerRef.createEmbeddedView(portal.templateRef);
108+
viewRef.detectChanges();
109+
108110
this.setDisposeFn(() => this._viewContainerRef.clear());
109111

110112
// TODO(jelbourn): return locals from view

0 commit comments

Comments
 (0)