fix(ivy): queries should match elements inside ng-container with the descendants: false option (#35384)

Before this change content queries with the `descendants: false` option, as implemented in ivy,
would not descendinto `<ng-container>` elements. This behaviour was different from the way the
View Engine worked. This change alligns ngIvy and VE behaviours when it comes to queries and the
`<ng-container>` elements and fixes a common bugs where a query target was placed inside the
`<ng-container>` element with a * directive on it.

Before:

```html
<needs-target>
  <ng-container *ngIf="condition">
    <div #target>...</div>  <!-- this node would NOT match -->
  </ng-container>
</needs-target>
```

After:

```html
<needs-target>
  <ng-container *ngIf="condition">
    <div #target>...</div>  <!-- this node WILL match -->
  </ng-container>
</needs-target>
```

Fixes #34768

PR Close #35384
This commit is contained in:
Pawel Kozlowski
2020-02-12 14:31:51 +01:00
committed by Alex Rickabaugh
parent 5fbfe6996a
commit 3f4e02b8c7
6 changed files with 272 additions and 81 deletions

View File

@ -361,19 +361,18 @@ describe('Query API', () => {
expect(comp.children.length).toBe(1);
});
onlyInIvy(
'Shallow queries don\'t cross ng-container boundaries in ivy (ng-container is treated as a regular element')
.it('should not cross ng-container boundaries with shallow queries', () => {
const template = `<needs-content-children-shallow>
it('should not cross ng-container boundaries with shallow queries', () => {
const template = `<needs-content-children-shallow>
<ng-container>
<div #q></div>
</ng-container>
</needs-content-children-shallow>`;
const view = createTestCmpAndDetectChanges(MyComp0, template);
const view = createTestCmpAndDetectChanges(MyComp0, template);
const comp = view.debugElement.children[0].injector.get(NeedsContentChildrenShallow);
expect(comp.children.length).toBe(0);
});
const comp = view.debugElement.children[0].injector.get(NeedsContentChildrenShallow);
expect(comp.children.length).toBe(1);
});
it('should contain the first descendant content child templateRef', () => {
const template = '<needs-content-child-template-ref-app>' +