fix(ivy): correct content projection with nested templates (#27755)

Previously ivy code generation was emmiting the projectionDef instruction in
a template where the <ng-content> tag was found. This code generation logic was
incorrect since the ivy runtime expects the projectionDef instruction to be present
in the main template only.

This PR ammends the code generation logic so that the projectionDef instruction is
emmitedin the main template only.

PR Close #27755
This commit is contained in:
Pawel Kozlowski
2018-12-19 15:03:36 +01:00
committed by Matias Niemelä
parent a833b98fd0
commit a0585c9a9a
3 changed files with 301 additions and 158 deletions

View File

@ -182,7 +182,7 @@ describe('projection', () => {
expect(main.nativeElement).toHaveText('OUTER(INNER(INNERINNER(A,BC)))');
});
fixmeIvy('FW-796: Content projection logic is incorrect for <ng-content> in nested templates')
fixmeIvy('FW-833: Directive / projected node matching against class name')
.it('should redistribute when the shadow dom changes', () => {
TestBed.configureTestingModule(
{declarations: [ConditionalContentComponent, ManualViewportDirective]});
@ -290,7 +290,7 @@ describe('projection', () => {
expect(main.nativeElement).toHaveText('SIMPLE()START(A)END');
});
fixmeIvy('FW-796: Content projection logic is incorrect for <ng-content> in nested templates')
fixmeIvy('FW-833: Directive / projected node matching against class name')
.it('should support moving ng-content around', () => {
TestBed.configureTestingModule({
declarations: [ConditionalContentComponent, ProjectDirective, ManualViewportDirective]
@ -430,7 +430,7 @@ describe('projection', () => {
});
}
fixmeIvy('FW-796: Content projection logic is incorrect for <ng-content> in nested templates')
fixmeIvy('FW-869: debugElement.queryAllNodes returns nodes in the wrong order')
.it('should support nested conditionals that contain ng-contents', () => {
TestBed.configureTestingModule(
{declarations: [ConditionalTextComponent, ManualViewportDirective]});
@ -474,7 +474,66 @@ describe('projection', () => {
'<cmp-a2>a2<cmp-b21>b21</cmp-b21><cmp-b22>b22</cmp-b22></cmp-a2>');
});
fixmeIvy('FW-796: Content projection logic is incorrect for <ng-content> in nested templates')
it('should project nodes into nested templates when the main template doesn\'t have <ng-content>',
() => {
@Component({
selector: 'content-in-template',
template:
`(<ng-template manual><ng-content select="[id=left]"></ng-content></ng-template>)`
})
class ContentInATemplateComponent {
}
TestBed.configureTestingModule(
{declarations: [ContentInATemplateComponent, ManualViewportDirective]});
TestBed.overrideComponent(
MainComp,
{set: {template: `<content-in-template><div id="left">A</div></content-in-template>`}});
const main = TestBed.createComponent(MainComp);
main.detectChanges();
expect(main.nativeElement).toHaveText('()');
let viewportElement =
main.debugElement.queryAllNodes(By.directive(ManualViewportDirective))[0];
viewportElement.injector.get(ManualViewportDirective).show();
expect(main.nativeElement).toHaveText('(A)');
});
it('should project nodes into nested templates and the main template', () => {
@Component({
selector: 'content-in-main-and-template',
template:
`<ng-content></ng-content>(<ng-template manual><ng-content select="[id=left]"></ng-content></ng-template>)`
})
class ContentInMainAndTemplateComponent {
}
TestBed.configureTestingModule(
{declarations: [ContentInMainAndTemplateComponent, ManualViewportDirective]});
TestBed.overrideComponent(MainComp, {
set: {
template:
`<content-in-main-and-template><div id="left">A</div>B</content-in-main-and-template>`
}
});
const main = TestBed.createComponent(MainComp);
main.detectChanges();
expect(main.nativeElement).toHaveText('B()');
let viewportElement = main.debugElement.queryAllNodes(By.directive(ManualViewportDirective))[0];
viewportElement.injector.get(ManualViewportDirective).show();
expect(main.nativeElement).toHaveText('B(A)');
});
fixmeIvy('FW-833: Directive / projected node matching against class name')
.it('should project filled view containers into a view container', () => {
TestBed.configureTestingModule(
{declarations: [ConditionalContentComponent, ManualViewportDirective]});