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) {