fix(core): correct order in ContentChildren query result (#18326)

Fixes #16568

PR Close #18326
This commit is contained in:
Marc Laval 2017-07-25 17:40:24 +02:00 committed by Miško Hevery
parent f2a2a6b478
commit f53f7241a0
2 changed files with 26 additions and 1 deletions

View File

@ -138,8 +138,13 @@ function calcQueryValues(
if (nodeDef.flags & NodeFlags.TypeElement && nodeDef.element !.template && if (nodeDef.flags & NodeFlags.TypeElement && nodeDef.element !.template &&
(nodeDef.element !.template !.nodeMatchedQueries & queryDef.filterId) === (nodeDef.element !.template !.nodeMatchedQueries & queryDef.filterId) ===
queryDef.filterId) { queryDef.filterId) {
// check embedded views that were attached at the place of their template.
const elementData = asElementData(view, i); 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) { if (nodeDef.flags & NodeFlags.EmbeddedViews) {
const embeddedViews = elementData.viewContainer !._embeddedViews; const embeddedViews = elementData.viewContainer !._embeddedViews;
for (let k = 0; k < embeddedViews.length; k++) { for (let k = 0; k < embeddedViews.length; k++) {

View File

@ -34,6 +34,7 @@ export function main() {
NeedsViewChild, NeedsViewChild,
NeedsStaticContentAndViewChild, NeedsStaticContentAndViewChild,
NeedsContentChild, NeedsContentChild,
DirectiveNeedsContentChild,
NeedsTpl, NeedsTpl,
NeedsNamedTpl, NeedsNamedTpl,
TextDirective, TextDirective,
@ -89,6 +90,20 @@ export function main() {
]); ]);
}); });
it('should contain the first content child when target is on <ng-template> with embedded view (issue #16568)',
() => {
const template =
'<div directive-needs-content-child><ng-template text="foo" [ngIf]="true"><div text="bar"></div></ng-template></div>' +
'<needs-content-child #q><ng-template text="foo" [ngIf]="true"><div text="bar"></div></ng-template></needs-content-child>';
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', () => { it('should contain the first view child', () => {
const template = '<needs-view-child #q></needs-view-child>'; const template = '<needs-view-child #q></needs-view-child>';
const view = createTestCmpAndDetectChanges(MyComp0, 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]); } 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: `<div *ngIf="shouldShow" text="foo"></div>`}) @Component({selector: 'needs-view-child', template: `<div *ngIf="shouldShow" text="foo"></div>`})
class NeedsViewChild implements AfterViewInit, AfterViewChecked { class NeedsViewChild implements AfterViewInit, AfterViewChecked {
shouldShow: boolean = true; shouldShow: boolean = true;