diff --git a/packages/core/src/render3/node_manipulation.ts b/packages/core/src/render3/node_manipulation.ts
index ef5eace965..80925708af 100644
--- a/packages/core/src/render3/node_manipulation.ts
+++ b/packages/core/src/render3/node_manipulation.ts
@@ -14,7 +14,7 @@ import {attachPatchData} from './context_discovery';
import {CONTAINER_HEADER_OFFSET, LContainer, NATIVE, unusedValueExportToPlacateAjd as unused1} from './interfaces/container';
import {ComponentDef} from './interfaces/definition';
import {NodeInjectorFactory} from './interfaces/injector';
-import {TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeType, TProjectionNode, TViewNode, unusedValueExportToPlacateAjd as unused2} from './interfaces/node';
+import {TElementContainerNode, TElementNode, TIcuContainerNode, TNode, TNodeFlags, TNodeType, TProjectionNode, TViewNode, unusedValueExportToPlacateAjd as unused2} from './interfaces/node';
import {unusedValueExportToPlacateAjd as unused3} from './interfaces/projection';
import {ProceduralRenderer3, RElement, RNode, RText, Renderer3, isProceduralRenderer, unusedValueExportToPlacateAjd as unused4} from './interfaces/renderer';
import {StylingContext} from './interfaces/styling';
@@ -844,23 +844,23 @@ function executeActionOnContainer(
/**
- * `executeActionOnElementContainer` performs an operation on the ng-container node and its child
- * nodes as specified by the `action` (insert, detach, destroy).
+ * `executeActionOnElementContainerOrIcuContainer` performs an operation on the ng-container node
+ * and its child nodes as specified by the `action` (insert, detach, destroy).
*
* @param renderer Renderer to use
* @param action action to perform (insert, detach, destroy)
* @param lView The LView which needs to be inserted, detached, destroyed.
- * @param tElementContainerNode The TNode associated with the ElementContainer.
+ * @param tNode The TNode associated with the `ElementContainer` or `IcuContainer`.
* @param renderParent parent DOM element for insertion/removal.
* @param beforeNode Before which node the insertions should happen.
*/
-function executeActionOnElementContainer(
+function executeActionOnElementContainerOrIcuContainer(
renderer: Renderer3, action: WalkTNodeTreeAction, lView: LView,
- tElementContainerNode: TElementContainerNode, renderParent: RElement | null,
+ tNode: TElementContainerNode | TIcuContainerNode, renderParent: RElement | null,
beforeNode: RNode | null | undefined) {
- const node = lView[tElementContainerNode.index];
+ const node = lView[tNode.index];
executeActionOnElementOrContainer(action, renderer, renderParent, node, beforeNode);
- let childTNode: TNode|null = tElementContainerNode.child;
+ let childTNode: TNode|null = tNode.child;
while (childTNode) {
executeActionOnNode(renderer, action, lView, childTNode, renderParent, beforeNode);
childTNode = childTNode.next;
@@ -871,9 +871,11 @@ function executeActionOnNode(
renderer: Renderer3, action: WalkTNodeTreeAction, lView: LView, tNode: TNode,
renderParent: RElement | null, beforeNode: RNode | null | undefined): void {
const elementContainerRootTNodeType = tNode.type;
- if (elementContainerRootTNodeType === TNodeType.ElementContainer) {
- executeActionOnElementContainer(
- renderer, action, lView, tNode as TElementContainerNode, renderParent, beforeNode);
+ if (elementContainerRootTNodeType === TNodeType.ElementContainer ||
+ elementContainerRootTNodeType === TNodeType.IcuContainer) {
+ executeActionOnElementContainerOrIcuContainer(
+ renderer, action, lView, tNode as TElementContainerNode | TIcuContainerNode, renderParent,
+ beforeNode);
} else if (elementContainerRootTNodeType === TNodeType.Projection) {
executeActionOnProjection(
renderer, action, lView, tNode as TProjectionNode, renderParent, beforeNode);
diff --git a/packages/core/test/acceptance/i18n_spec.ts b/packages/core/test/acceptance/i18n_spec.ts
index ef4c5c86dc..fabf81798d 100644
--- a/packages/core/test/acceptance/i18n_spec.ts
+++ b/packages/core/test/acceptance/i18n_spec.ts
@@ -772,6 +772,40 @@ onlyInIvy('Ivy i18n logic').describe('runtime i18n', () => {
expect(fixture.debugElement.nativeElement.innerHTML)
.toBe('ONE
');
});
+
+ it('with nested containers', () => {
+ @Component({
+ selector: 'comp',
+ template: `
+
+
+ {type, select, A { A } B { B } other { C }}
+
+
+ {type, select, A1 { A1 } B1 { B1 } other { C1 }}
+
+
+ `,
+ })
+ class Comp {
+ type = 'A';
+ visible = true;
+ isVisible() { return true; }
+ }
+
+ TestBed.configureTestingModule({declarations: [Comp]});
+
+ const fixture = TestBed.createComponent(Comp);
+ fixture.detectChanges();
+
+ expect(fixture.debugElement.nativeElement.innerHTML).toContain('A');
+
+ fixture.componentInstance.visible = false;
+ fixture.detectChanges();
+
+ expect(fixture.debugElement.nativeElement.innerHTML).not.toContain('A');
+ expect(fixture.debugElement.nativeElement.innerHTML).toContain('C1');
+ });
});
describe('should support attributes', () => {
diff --git a/packages/core/test/bundling/todo/bundle.golden_symbols.json b/packages/core/test/bundling/todo/bundle.golden_symbols.json
index 2eb9133154..a8f14d47cd 100644
--- a/packages/core/test/bundling/todo/bundle.golden_symbols.json
+++ b/packages/core/test/bundling/todo/bundle.golden_symbols.json
@@ -675,10 +675,10 @@
"name": "executeActionOnContainer"
},
{
- "name": "executeActionOnElementContainer"
+ "name": "executeActionOnElementOrContainer"
},
{
- "name": "executeActionOnElementOrContainer"
+ "name": "executeActionOnElementContainerOrIcuContainer"
},
{
"name": "executeActionOnNode"