fix(core): correct order in ContentChildren query result (#18326)
Fixes #16568 PR Close #18326
This commit is contained in:
parent
f2a2a6b478
commit
f53f7241a0
|
@ -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++) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue