Skip to content

Commit af9ced9

Browse files
pkozlowski-opensourcekara
authored andcommitted
fix(ivy): project ng-container nodes (angular#25354)
PR Close angular#25354
1 parent c6e5b97 commit af9ced9

File tree

2 files changed

+95
-1
lines changed

2 files changed

+95
-1
lines changed

packages/core/src/render3/node_manipulation.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,14 @@ export function appendProjectedNode(
708708
for (let i = 0; i < views.length; i++) {
709709
addRemoveViewFromContainer(node as LContainerNode, views[i], true, node.native);
710710
}
711+
} else if (node.tNode.type === TNodeType.ElementContainer) {
712+
let ngContainerChild = getChildLNode(node as LElementContainerNode);
713+
while (ngContainerChild) {
714+
appendProjectedNode(
715+
ngContainerChild as LElementNode | LElementContainerNode | LTextNode | LContainerNode,
716+
currentParent, currentView, renderParent);
717+
ngContainerChild = getNextLNode(ngContainerChild);
718+
}
711719
}
712720
if (node.dynamicLContainerNode) {
713721
node.dynamicLContainerNode.data[RENDER_PARENT] = renderParent;

packages/core/test/render3/content_spec.ts

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {Input, TemplateRef, ViewContainerRef, ViewRef} from '../../src/core';
1212
import {defineDirective} from '../../src/render3/definition';
1313
import {injectTemplateRef, injectViewContainerRef} from '../../src/render3/di';
1414
import {AttributeMarker, detectChanges} from '../../src/render3/index';
15-
import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, loadDirective, projection, projectionDef, text} from '../../src/render3/instructions';
15+
import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementContainerEnd, elementContainerStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, loadDirective, projection, projectionDef, text} from '../../src/render3/instructions';
1616
import {RenderFlags} from '../../src/render3/interfaces/definition';
1717

1818
import {NgIf} from './common_with_def';
@@ -1167,6 +1167,92 @@ describe('content projection', () => {
11671167
'<projection-comp>Before<div>B</div><p>456</p>After</projection-comp></parent-comp>');
11681168
});
11691169

1170+
it('should project ng-container at the content root', () => {
1171+
1172+
`<ng-content></ng-content>`;
1173+
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
1174+
if (rf & RenderFlags.Create) {
1175+
projectionDef();
1176+
projection(0);
1177+
}
1178+
});
1179+
1180+
`<child>
1181+
<ng-container>
1182+
<ng-container>
1183+
content
1184+
</ng-container>
1185+
</ng-container>
1186+
</child>`;
1187+
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) {
1188+
if (rf & RenderFlags.Create) {
1189+
elementStart(0, 'child');
1190+
{
1191+
elementContainerStart(1);
1192+
{
1193+
elementContainerStart(2);
1194+
{ text(3, 'content'); }
1195+
elementContainerEnd();
1196+
}
1197+
elementContainerEnd();
1198+
}
1199+
elementEnd();
1200+
}
1201+
}, [Child]);
1202+
1203+
const parent = renderComponent(Parent);
1204+
expect(toHtml(parent)).toEqual('<child>content</child>');
1205+
});
1206+
1207+
it('should re-project ng-container at the content root', () => {
1208+
1209+
`<ng-content></ng-content>`;
1210+
const GrandChild = createComponent('grand-child', function(rf: RenderFlags, ctx: any) {
1211+
if (rf & RenderFlags.Create) {
1212+
projectionDef();
1213+
projection(0);
1214+
}
1215+
});
1216+
1217+
`<grand-child>
1218+
<ng-content></ng-content>
1219+
</grand-child>`;
1220+
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
1221+
if (rf & RenderFlags.Create) {
1222+
projectionDef();
1223+
elementStart(0, 'grand-child');
1224+
{ projection(1); }
1225+
elementEnd();
1226+
}
1227+
}, [GrandChild]);
1228+
1229+
`<child>
1230+
<ng-container>
1231+
<ng-container>
1232+
content
1233+
</ng-container>
1234+
</ng-container>
1235+
</child>`;
1236+
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) {
1237+
if (rf & RenderFlags.Create) {
1238+
elementStart(0, 'child');
1239+
{
1240+
elementContainerStart(1);
1241+
{
1242+
elementContainerStart(2);
1243+
{ text(3, 'content'); }
1244+
elementContainerEnd();
1245+
}
1246+
elementContainerEnd();
1247+
}
1248+
elementEnd();
1249+
}
1250+
}, [Child]);
1251+
1252+
const parent = renderComponent(Parent);
1253+
expect(toHtml(parent)).toEqual('<child><grand-child>content</grand-child></child>');
1254+
});
1255+
11701256
describe('with selectors', () => {
11711257

11721258
it('should project nodes using attribute selectors', () => {

0 commit comments

Comments
 (0)