diff --git a/packages/core/src/render3/node_manipulation.ts b/packages/core/src/render3/node_manipulation.ts index 3d2c023f1a..25ee3abd9a 100644 --- a/packages/core/src/render3/node_manipulation.ts +++ b/packages/core/src/render3/node_manipulation.ts @@ -708,6 +708,14 @@ export function appendProjectedNode( for (let i = 0; i < views.length; i++) { addRemoveViewFromContainer(node as LContainerNode, views[i], true, node.native); } + } else if (node.tNode.type === TNodeType.ElementContainer) { + let ngContainerChild = getChildLNode(node as LElementContainerNode); + while (ngContainerChild) { + appendProjectedNode( + ngContainerChild as LElementNode | LElementContainerNode | LTextNode | LContainerNode, + currentParent, currentView, renderParent); + ngContainerChild = getNextLNode(ngContainerChild); + } } if (node.dynamicLContainerNode) { node.dynamicLContainerNode.data[RENDER_PARENT] = renderParent; diff --git a/packages/core/test/render3/content_spec.ts b/packages/core/test/render3/content_spec.ts index d30e2e7df1..4d69183275 100644 --- a/packages/core/test/render3/content_spec.ts +++ b/packages/core/test/render3/content_spec.ts @@ -12,7 +12,7 @@ import {Input, TemplateRef, ViewContainerRef, ViewRef} from '../../src/core'; import {defineDirective} from '../../src/render3/definition'; import {injectTemplateRef, injectViewContainerRef} from '../../src/render3/di'; import {AttributeMarker, detectChanges} from '../../src/render3/index'; -import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, loadDirective, projection, projectionDef, text} from '../../src/render3/instructions'; +import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementContainerEnd, elementContainerStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, loadDirective, projection, projectionDef, text} from '../../src/render3/instructions'; import {RenderFlags} from '../../src/render3/interfaces/definition'; import {NgIf} from './common_with_def'; @@ -1167,6 +1167,92 @@ describe('content projection', () => { 'Before
B

456

After
'); }); + it('should project ng-container at the content root', () => { + + ``; + const Child = createComponent('child', function(rf: RenderFlags, ctx: any) { + if (rf & RenderFlags.Create) { + projectionDef(); + projection(0); + } + }); + + ` + + + content + + + `; + const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) { + if (rf & RenderFlags.Create) { + elementStart(0, 'child'); + { + elementContainerStart(1); + { + elementContainerStart(2); + { text(3, 'content'); } + elementContainerEnd(); + } + elementContainerEnd(); + } + elementEnd(); + } + }, [Child]); + + const parent = renderComponent(Parent); + expect(toHtml(parent)).toEqual('content'); + }); + + it('should re-project ng-container at the content root', () => { + + ``; + const GrandChild = createComponent('grand-child', function(rf: RenderFlags, ctx: any) { + if (rf & RenderFlags.Create) { + projectionDef(); + projection(0); + } + }); + + ` + + `; + const Child = createComponent('child', function(rf: RenderFlags, ctx: any) { + if (rf & RenderFlags.Create) { + projectionDef(); + elementStart(0, 'grand-child'); + { projection(1); } + elementEnd(); + } + }, [GrandChild]); + + ` + + + content + + + `; + const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) { + if (rf & RenderFlags.Create) { + elementStart(0, 'child'); + { + elementContainerStart(1); + { + elementContainerStart(2); + { text(3, 'content'); } + elementContainerEnd(); + } + elementContainerEnd(); + } + elementEnd(); + } + }, [Child]); + + const parent = renderComponent(Parent); + expect(toHtml(parent)).toEqual('content'); + }); + describe('with selectors', () => { it('should project nodes using attribute selectors', () => {