From f53f7241a0c0cb262eab184d3f63c8600d2ee41a Mon Sep 17 00:00:00 2001 From: Marc Laval Date: Tue, 25 Jul 2017 17:40:24 +0200 Subject: [PATCH] fix(core): correct order in ContentChildren query result (#18326) Fixes #16568 PR Close #18326 --- packages/core/src/view/query.ts | 7 ++++++- .../test/linker/query_integration_spec.ts | 20 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/packages/core/src/view/query.ts b/packages/core/src/view/query.ts index 842216207e..b211b1f002 100644 --- a/packages/core/src/view/query.ts +++ b/packages/core/src/view/query.ts @@ -138,8 +138,13 @@ function calcQueryValues( if (nodeDef.flags & NodeFlags.TypeElement && nodeDef.element !.template && (nodeDef.element !.template !.nodeMatchedQueries & queryDef.filterId) === queryDef.filterId) { - // check embedded views that were attached at the place of their template. const elementData = asElementData(view, i); + // check embedded views that were attached at the place of their template, + // but process child nodes first if some match the query (see issue #16568) + if ((nodeDef.childMatchedQueries & queryDef.filterId) === queryDef.filterId) { + calcQueryValues(view, i + 1, i + nodeDef.childCount, queryDef, values); + i += nodeDef.childCount; + } if (nodeDef.flags & NodeFlags.EmbeddedViews) { const embeddedViews = elementData.viewContainer !._embeddedViews; for (let k = 0; k < embeddedViews.length; k++) { diff --git a/packages/core/test/linker/query_integration_spec.ts b/packages/core/test/linker/query_integration_spec.ts index 92b8fa0047..d3b5cc8b19 100644 --- a/packages/core/test/linker/query_integration_spec.ts +++ b/packages/core/test/linker/query_integration_spec.ts @@ -34,6 +34,7 @@ export function main() { NeedsViewChild, NeedsStaticContentAndViewChild, NeedsContentChild, + DirectiveNeedsContentChild, NeedsTpl, NeedsNamedTpl, TextDirective, @@ -89,6 +90,20 @@ export function main() { ]); }); + it('should contain the first content child when target is on with embedded view (issue #16568)', + () => { + const template = + '
' + + '
'; + const view = createTestCmp(MyComp0, template); + view.detectChanges(); + const q: NeedsContentChild = view.debugElement.children[1].references !['q']; + expect(q.child.text).toEqual('foo'); + const directive: DirectiveNeedsContentChild = + view.debugElement.children[0].injector.get(DirectiveNeedsContentChild); + expect(directive.child.text).toEqual('foo'); + }); + it('should contain the first view child', () => { const template = ''; const view = createTestCmpAndDetectChanges(MyComp0, template); @@ -650,6 +665,11 @@ class NeedsContentChild implements AfterContentInit, AfterContentChecked { ngAfterContentChecked() { this.logs.push(['check', this.child ? this.child.text : null]); } } +@Directive({selector: '[directive-needs-content-child]'}) +class DirectiveNeedsContentChild { + @ContentChild(TextDirective) child: TextDirective; +} + @Component({selector: 'needs-view-child', template: `
`}) class NeedsViewChild implements AfterViewInit, AfterViewChecked { shouldShow: boolean = true;