From 8fa099158e54f96dd60f4612862e3400a6f0d9bd Mon Sep 17 00:00:00 2001 From: Pawel Kozlowski Date: Wed, 22 Aug 2018 17:30:27 +0200 Subject: [PATCH] fix(ivy): allow queries for ng-container without read option (#25617) PR Close #25617 --- packages/core/src/render3/di.ts | 10 +++-- .../test/render3/common_integration_spec.ts | 4 +- packages/core/test/render3/query_spec.ts | 37 ++++++++++++++++++- 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/packages/core/src/render3/di.ts b/packages/core/src/render3/di.ts index 1db254ca4b..5b036f4a22 100644 --- a/packages/core/src/render3/di.ts +++ b/packages/core/src/render3/di.ts @@ -557,17 +557,21 @@ export const QUERY_READ_ELEMENT_REF = export const QUERY_READ_FROM_NODE = (new ReadFromInjectorFn((injector: LInjector, node: LNode, directiveIdx: number) => { - ngDevMode && assertNodeOfPossibleTypes(node, TNodeType.Container, TNodeType.Element); + ngDevMode && assertNodeOfPossibleTypes( + node, TNodeType.Container, TNodeType.Element, TNodeType.ElementContainer); if (directiveIdx > -1) { return node.view[DIRECTIVES] ![directiveIdx]; } - if (node.tNode.type === TNodeType.Element) { + if (node.tNode.type === TNodeType.Element || node.tNode.type === TNodeType.ElementContainer) { return getOrCreateElementRef(injector); } if (node.tNode.type === TNodeType.Container) { return getOrCreateTemplateRef(injector); } - throw new Error('fail'); + if (ngDevMode) { + // should never happen + throw new Error(`Unexpected node type: ${node.tNode.type}`); + } }) as any as QueryReadType); /** A ref to a node's native element. */ diff --git a/packages/core/test/render3/common_integration_spec.ts b/packages/core/test/render3/common_integration_spec.ts index faf7f88469..10bdf36cac 100644 --- a/packages/core/test/render3/common_integration_spec.ts +++ b/packages/core/test/render3/common_integration_spec.ts @@ -9,7 +9,7 @@ import {NgForOfContext} from '@angular/common'; import {AttributeMarker, defineComponent, templateRefExtractor} from '../../src/render3/index'; -import {bind, template, elementEnd, elementProperty, elementStart, getCurrentView, interpolation1, interpolation2, interpolation3, interpolationV, listener, load, nextContext, restoreView, text, textBinding, elementContainerStart, elementContainerEnd} from '../../src/render3/instructions'; +import {bind, template, elementEnd, elementProperty, elementStart, getCurrentView, interpolation1, interpolation2, interpolation3, interpolationV, listener, load, nextContext, restoreView, text, textBinding, elementContainerStart, elementContainerEnd, reference} from '../../src/render3/instructions'; import {RenderFlags} from '../../src/render3/interfaces/definition'; import {NgForOf, NgIf, NgTemplateOutlet} from './common_with_def'; @@ -948,7 +948,7 @@ describe('@angular/common integration', () => { elementContainerEnd(); } if (rf & RenderFlags.Update) { - const tplRef = load(1); + const tplRef = reference(1); elementProperty(2, 'ngTemplateOutlet', bind(myApp.showing ? tplRef : null)); } }, diff --git a/packages/core/test/render3/query_spec.ts b/packages/core/test/render3/query_spec.ts index defe635c9b..3fb5fc285c 100644 --- a/packages/core/test/render3/query_spec.ts +++ b/packages/core/test/render3/query_spec.ts @@ -370,7 +370,7 @@ describe('query', () => { /** * * class Cmpt { - * @ViewChildren('foo') query; + * @ViewChildren('foo', {read: ElementRef}) query; * } */ const Cmpt = createComponent( @@ -401,6 +401,41 @@ describe('query', () => { expect(qList.first.nativeElement).toEqual(elToQuery); }); + it('should query for and read ElementRef without explicit read option', () => { + let elToQuery; + /** + * + * class Cmpt { + * @ViewChildren('foo') query; + * } + */ + const Cmpt = createComponent( + 'cmpt', + function(rf: RenderFlags, ctx: any) { + if (rf & RenderFlags.Create) { + elementContainerStart(1, null, ['foo', '']); + elToQuery = loadElement(1).native; + elementContainerEnd(); + } + }, + 3, 0, [], [], + function(rf: RenderFlags, ctx: any) { + if (rf & RenderFlags.Create) { + query(0, ['foo'], true, QUERY_READ_FROM_NODE); + } + if (rf & RenderFlags.Update) { + let tmp: any; + queryRefresh(tmp = load>(0)) && (ctx.query = tmp as QueryList); + } + }); + + const cmptInstance = renderComponent(Cmpt); + const qList = (cmptInstance.query as QueryList); + expect(qList.length).toBe(1); + expect(isElementRef(qList.first)).toBeTruthy(); + expect(qList.first.nativeElement).toEqual(elToQuery); + }); + /** * BREAKING CHANGE: this tests asserts different behaviour as compared to Renderer2 when it * comes to descendants: false option and .