diff --git a/packages/core/test/render3/content_spec.ts b/packages/core/test/render3/content_spec.ts index b8611afd90..6625bd58ba 100644 --- a/packages/core/test/render3/content_spec.ts +++ b/packages/core/test/render3/content_spec.ts @@ -9,10 +9,10 @@ import {SelectorFlags} from '@angular/core/src/render3/interfaces/projection'; import {AttributeMarker, detectChanges} from '../../src/render3/index'; -import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementContainerEnd, elementContainerStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, projection, projectionDef, template, text} from '../../src/render3/instructions'; +import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementContainerEnd, elementContainerStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, projection, projectionDef, template, text, textBinding, interpolation1} from '../../src/render3/instructions'; import {RenderFlags} from '../../src/render3/interfaces/definition'; -import {NgIf} from './common_with_def'; +import {NgIf, NgForOf} from './common_with_def'; import {ComponentFixture, createComponent, getDirectiveOnNode, renderComponent, toHtml} from './render_util'; describe('content projection', () => { @@ -45,7 +45,7 @@ describe('content projection', () => { expect(toHtml(parent)).toEqual('
content
'); }); - it('should project content when root.', () => { + it('should project content when is at a template root', () => { /** */ const Child = createComponent('child', function(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { @@ -231,7 +231,7 @@ describe('content projection', () => { }); it('should project containers', () => { - /**
*/ + /**
*/ const Child = createComponent('child', function(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { projectionDef(); @@ -824,7 +824,6 @@ describe('content projection', () => { function IfTemplate(rf1: RenderFlags, ctx: any) { if (rf1 & RenderFlags.Create) { - projectionDef(); projection(0); } } @@ -889,7 +888,6 @@ describe('content projection', () => { function IfTemplate(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { - projectionDef(); projection(0); } } @@ -931,6 +929,74 @@ describe('content projection', () => { expect(fixture.html).toEqual('Before-
A
Some text-After
'); }); + it('should project into dynamic views with specific selectors', () => { + /** + * + * Before- + * + * + * + * -After + */ + const Child = createComponent('child', function(rf: RenderFlags, ctx: any) { + if (rf & RenderFlags.Create) { + projectionDef([[['div']]], ['div']); + projection(0); + text(1, 'Before-'); + template(2, IfTemplate, 1, 0, '', [AttributeMarker.SelectOnly, 'ngIf']); + text(3, '-After'); + } + if (rf & RenderFlags.Update) { + elementProperty(2, 'ngIf', bind(ctx.showing)); + } + + }, 4, 1, [NgIf]); + + function IfTemplate(rf1: RenderFlags) { + if (rf1 & RenderFlags.Create) { + projection(0, 1); + } + } + + let child: {showing: boolean}; + /** + * + *
A
+ * B + *
+ */ + const App = createComponent('app', function(rf: RenderFlags, ctx: any) { + if (rf & RenderFlags.Create) { + elementStart(0, 'child'); + { + elementStart(1, 'div'); + { text(2, 'A'); } + elementEnd(); + elementStart(3, 'span'); + { text(4, 'B'); } + elementEnd(); + } + elementEnd(); + + // testing + child = getDirectiveOnNode(0); + } + }, 5, 0, [Child]); + + const fixture = new ComponentFixture(App); + child !.showing = true; + fixture.update(); + expect(fixture.html).toEqual('BBefore-
A
-After
'); + + child !.showing = false; + fixture.update(); + expect(fixture.html).toEqual('BBefore--After'); + + child !.showing = true; + fixture.update(); + expect(fixture.html).toEqual('BBefore-
A
-After
'); + }); + it('should project nodes into the last ng-content', () => { /** *
@@ -1027,6 +1093,52 @@ describe('content projection', () => { expect(toHtml(parent)).toEqual('
content
'); }); + // https://stackblitz.com/edit/angular-ceqmnw?file=src%2Fapp%2Fapp.component.ts + it('should project nodes into the last ng-content unrolled by ngFor', () => { + const items = [1, 2]; + + /** +
+ ({{index}}): +
+ */ + const Child = createComponent('child', function(rf: RenderFlags, ctx: any) { + if (rf & RenderFlags.Create) { + projectionDef(); + { template(0, ForTemplate, 3, 1, undefined, ['ngForOf', '']); } + } + if (rf & RenderFlags.Update) { + elementProperty(0, 'ngForOf', bind(items)); + } + }, 1, 1, [NgForOf]); + + function ForTemplate(rf1: RenderFlags, ctx: {index: number}) { + if (rf1 & RenderFlags.Create) { + elementStart(0, 'div'); + text(1); + projection(2); + elementEnd(); + } + if (rf1 & RenderFlags.Update) { + textBinding(1, interpolation1('(', ctx.index, '):')); + } + } + + /** + * content + */ + const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) { + if (rf & RenderFlags.Create) { + elementStart(0, 'child'); + { text(1, 'content'); } + elementEnd(); + } + }, 2, 0, [Child]); + + const parent = renderComponent(Parent); + expect(toHtml(parent)).toEqual('
(0):
(1):content
'); + }); + it('should project with multiple instances of a component with projection', () => { const ProjectionComp = createComponent('projection-comp', function(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) {