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"