diff --git a/packages/core/src/render3/view_ref.ts b/packages/core/src/render3/view_ref.ts index a97d2dcf3f282..a88f43d3541d1 100644 --- a/packages/core/src/render3/view_ref.ts +++ b/packages/core/src/render3/view_ref.ts @@ -306,7 +306,7 @@ function collectNativeNodes(lView: LView, tNode: TNode | null, result: any[]): a while (tNode !== null) { ngDevMode && assertNodeOfPossibleTypes( tNode, TNodeType.Element, TNodeType.Container, TNodeType.Projection, - TNodeType.ElementContainer); + TNodeType.ElementContainer, TNodeType.IcuContainer); const lNode = lView[tNode.index]; if (lNode !== null) { @@ -326,9 +326,10 @@ function collectNativeNodes(lView: LView, tNode: TNode | null, result: any[]): a } } - if (tNode.type === TNodeType.ElementContainer) { + const tNodeType = tNode.type; + if (tNodeType === TNodeType.ElementContainer || tNodeType === TNodeType.IcuContainer) { collectNativeNodes(lView, tNode.child, result); - } else if (tNode.type === TNodeType.Projection) { + } else if (tNodeType === TNodeType.Projection) { const componentView = findComponentView(lView); const componentHost = componentView[T_HOST] as TElementNode; const parentView = getLViewParent(componentView); diff --git a/packages/core/test/acceptance/template_ref_spec.ts b/packages/core/test/acceptance/template_ref_spec.ts index 8a470d1b3e024..9c037e8614165 100644 --- a/packages/core/test/acceptance/template_ref_spec.ts +++ b/packages/core/test/acceptance/template_ref_spec.ts @@ -9,7 +9,7 @@ import {Component, TemplateRef, ViewChild, ViewContainerRef} from '@angular/core'; import {TestBed} from '@angular/core/testing'; import {expect} from '@angular/platform-browser/testing/src/matchers'; -import {onlyInIvy} from '@angular/private/testing'; +import {ivyEnabled, onlyInIvy} from '@angular/private/testing'; describe('TemplateRef', () => { describe('rootNodes', () => { @@ -203,7 +203,7 @@ describe('TemplateRef', () => { expect(embeddedView.rootNodes[2].nodeType).toBe(Node.TEXT_NODE); }); - it('should descend into element containers when retrieving root nodes', () => { + it('should descend into element containers', () => { @Component({ template: ` @@ -223,10 +223,47 @@ describe('TemplateRef', () => { fixture.detectChanges(); const embeddedView = fixture.componentInstance.templateRef.createEmbeddedView({}); + embeddedView.detectChanges(); expect(embeddedView.rootNodes.length).toBe(2); expect(embeddedView.rootNodes[0].nodeType).toBe(Node.COMMENT_NODE); expect(embeddedView.rootNodes[1].nodeType).toBe(Node.TEXT_NODE); }); + + it('should descend into ICU containers', () => { + @Component({ + template: ` + + Updated {minutes, plural, =0 {just now} =1 {one minute ago} other {several minutes ago}} + + ` + }) + class App { + @ViewChild('templateRef', {static: true}) + templateRef !: TemplateRef; + minutes = 0; + } + + TestBed.configureTestingModule({ + declarations: [App], + }); + const fixture = TestBed.createComponent(App); + fixture.detectChanges(); + + const embeddedView = fixture.componentInstance.templateRef.createEmbeddedView({}); + embeddedView.detectChanges(); + + if (ivyEnabled) { + expect(embeddedView.rootNodes.length).toBe(4); + expect(embeddedView.rootNodes[0].nodeType).toBe(Node.COMMENT_NODE); // ng-container + expect(embeddedView.rootNodes[1].nodeType).toBe(Node.TEXT_NODE); // "Updated " text + expect(embeddedView.rootNodes[2].nodeType).toBe(Node.COMMENT_NODE); // ICU container + expect(embeddedView.rootNodes[3].nodeType).toBe(Node.TEXT_NODE); // "one minute ago" text + } else { + // ViewEngine seems to produce very different DOM structure as compared to ivy + // when it comes to ICU containers - this needs more investigation / fix. + expect(embeddedView.rootNodes.length).toBe(8); + } + }); }); });