diff --git a/packages/core/src/render3/node_manipulation.ts b/packages/core/src/render3/node_manipulation.ts
index b5cbb73219..4663868be5 100644
--- a/packages/core/src/render3/node_manipulation.ts
+++ b/packages/core/src/render3/node_manipulation.ts
@@ -502,6 +502,12 @@ function executePipeOnDestroys(viewData: LViewData): void {
export function getRenderParent(tNode: TNode, currentView: LViewData): RElement|null {
if (canInsertNativeNode(tNode, currentView)) {
const hostTNode = currentView[HOST_NODE];
+
+ const tNodeParent = tNode.parent;
+ if (tNodeParent != null && tNodeParent.type === TNodeType.ElementContainer) {
+ tNode = getHighestElementContainer(tNodeParent);
+ }
+
return tNode.parent == null && hostTNode !.type === TNodeType.View ?
getContainerRenderParent(hostTNode as TViewNode, currentView) :
getParentNative(tNode, currentView) as RElement;
@@ -626,8 +632,7 @@ export function appendChild(
renderer, lContainer[RENDER_PARENT] !, childEl,
getBeforeNodeForView(index, views, lContainer[NATIVE]));
} else if (parentTNode.type === TNodeType.ElementContainer) {
- let elementContainer = getHighestElementContainer(childTNode);
- let renderParent: RElement = getRenderParent(elementContainer, currentView) !;
+ const renderParent: RElement = getRenderParent(childTNode, currentView) !;
nativeInsertBefore(renderer, renderParent, childEl, parentEl);
} else {
isProceduralRenderer(renderer) ? renderer.appendChild(parentEl !as RElement, childEl) :
diff --git a/packages/core/test/render3/integration_spec.ts b/packages/core/test/render3/integration_spec.ts
index 1f17564e53..9426cd40d2 100644
--- a/packages/core/test/render3/integration_spec.ts
+++ b/packages/core/test/render3/integration_spec.ts
@@ -943,6 +943,116 @@ describe('render3 integration test', () => {
expect(directive !.elRef.nativeElement.nodeType).toBe(Node.COMMENT_NODE);
});
+ it('should support ViewContainerRef when ng-container is at the root of a view', () => {
+
+ function ContentTemplate(rf: RenderFlags, ctx: any) {
+ if (rf & RenderFlags.Create) {
+ text(0, 'Content');
+ }
+ }
+
+ class Directive {
+ contentTpl: TemplateRef<{}>|null = null;
+
+ constructor(private _vcRef: ViewContainerRef) {}
+
+ insertView() { this._vcRef.createEmbeddedView(this.contentTpl as TemplateRef<{}>); }
+
+ clear() { this._vcRef.clear(); }
+
+ static ngDirectiveDef = defineDirective({
+ type: Directive,
+ selectors: [['', 'dir', '']],
+ factory: () => directive = new Directive(directiveInject(ViewContainerRef as any)),
+ inputs: {contentTpl: 'contentTpl'},
+ });
+ }
+
+ let directive: Directive;
+
+ /**
+ *
+ * Content
+ *
+ */
+ const App = createComponent('app', function(rf: RenderFlags) {
+ if (rf & RenderFlags.Create) {
+ elementContainerStart(0, [AttributeMarker.SelectOnly, 'dir']);
+ template(1, ContentTemplate, 1, 0, '', null, ['content', ''], templateRefExtractor);
+ elementContainerEnd();
+ }
+ if (rf & RenderFlags.Update) {
+ const content = reference(2) as any;
+ elementProperty(0, 'contentTpl', bind(content));
+ }
+ }, 3, 1, [Directive]);
+
+
+ const fixture = new ComponentFixture(App);
+ expect(fixture.html).toEqual('');
+
+ directive !.insertView();
+ fixture.update();
+ expect(fixture.html).toEqual('Content');
+
+ directive !.clear();
+ fixture.update();
+ expect(fixture.html).toEqual('');
+ });
+
+ it('should support ViewContainerRef on inside ', () => {
+ function ContentTemplate(rf: RenderFlags, ctx: any) {
+ if (rf & RenderFlags.Create) {
+ text(0, 'Content');
+ }
+ }
+
+ class Directive {
+ constructor(private _tplRef: TemplateRef<{}>, private _vcRef: ViewContainerRef) {}
+
+ insertView() { this._vcRef.createEmbeddedView(this._tplRef); }
+
+ clear() { this._vcRef.clear(); }
+
+ static ngDirectiveDef = defineDirective({
+ type: Directive,
+ selectors: [['', 'dir', '']],
+ factory:
+ () => directive = new Directive(
+ directiveInject(TemplateRef as any), directiveInject(ViewContainerRef as any)),
+ });
+ }
+
+ let directive: Directive;
+
+ /**
+ *
+ * Content
+ *
+ */
+ const App = createComponent('app', function(rf: RenderFlags) {
+ if (rf & RenderFlags.Create) {
+ elementContainerStart(0);
+ template(
+ 1, ContentTemplate, 1, 0, '', [AttributeMarker.SelectOnly, 'dir'], [],
+ templateRefExtractor);
+ elementContainerEnd();
+ }
+ }, 2, 0, [Directive]);
+
+
+ const fixture = new ComponentFixture(App);
+ expect(fixture.html).toEqual('');
+
+ directive !.insertView();
+ fixture.update();
+ expect(fixture.html).toEqual('Content');
+
+ directive !.clear();
+ fixture.update();
+ expect(fixture.html).toEqual('');
+ });
+
it('should not set any attributes', () => {
/**
*