fix(ivy): correct position for re-projected containers (#24721)
PR Close #24721
This commit is contained in:
parent
3553977bd7
commit
a294e0dd79
|
@ -9,7 +9,7 @@
|
|||
import {assertEqual, assertLessThan} from './assert';
|
||||
import {NO_CHANGE, bindingUpdated, createLNode, getPreviousOrParentNode, getRenderer, getViewData, load, resetApplicationState} from './instructions';
|
||||
import {RENDER_PARENT} from './interfaces/container';
|
||||
import {LContainerNode, LElementNode, LNode, TNodeType} from './interfaces/node';
|
||||
import {LContainerNode, LElementNode, LNode, TContainerNode, TNodeType} from './interfaces/node';
|
||||
import {BINDING_INDEX, HEADER_OFFSET, TVIEW} from './interfaces/view';
|
||||
import {appendChild, createTextNode, getParentLNode, removeChild} from './node_manipulation';
|
||||
import {stringify} from './util';
|
||||
|
@ -241,7 +241,8 @@ function appendI18nNode(node: LNode, parentNode: LNode, previousNode: LNode) {
|
|||
appendChild(parentNode, node.native || null, viewData);
|
||||
|
||||
// On first pass, re-organize node tree to put this node in the correct position.
|
||||
if (node.view[TVIEW].firstTemplatePass) {
|
||||
const firstTemplatePass = node.view[TVIEW].firstTemplatePass;
|
||||
if (firstTemplatePass) {
|
||||
node.tNode.next = null;
|
||||
if (previousNode === parentNode && node.tNode !== parentNode.tNode.child) {
|
||||
node.tNode.next = parentNode.tNode.child;
|
||||
|
@ -257,7 +258,10 @@ function appendI18nNode(node: LNode, parentNode: LNode, previousNode: LNode) {
|
|||
// (node.native as RComment).textContent = 'test';
|
||||
// console.log(node.native);
|
||||
appendChild(parentNode, node.dynamicLContainerNode.native || null, viewData);
|
||||
node.pNextOrParent = node.dynamicLContainerNode;
|
||||
if (firstTemplatePass) {
|
||||
node.tNode.dynamicContainerNode = node.dynamicLContainerNode.tNode;
|
||||
node.dynamicLContainerNode.tNode.parent = node.tNode as TContainerNode;
|
||||
}
|
||||
return node.dynamicLContainerNode;
|
||||
}
|
||||
|
||||
|
|
|
@ -1920,7 +1920,7 @@ export function projectionDef(
|
|||
* @param appendedFirst First node of the linked list to append.
|
||||
* @param appendedLast Last node of the linked list to append.
|
||||
*/
|
||||
function appendToProjectionNode(
|
||||
function addToProjectionList(
|
||||
projectionNode: LProjectionNode,
|
||||
appendedFirst: LElementNode | LTextNode | LContainerNode | null,
|
||||
appendedLast: LElementNode | LTextNode | LContainerNode | null) {
|
||||
|
@ -1965,36 +1965,33 @@ export function projection(
|
|||
const distributedNodes = loadInternal(localIndex, componentLView) as Array<LNode[]>;
|
||||
const nodesForSelector = distributedNodes[selectorIndex];
|
||||
|
||||
// build the linked list of projected nodes:
|
||||
const currentParent = getParentLNode(node);
|
||||
const canInsert = canInsertNativeNode(currentParent, viewData);
|
||||
const renderParent = currentParent.tNode.type === TNodeType.View ?
|
||||
(getParentLNode(currentParent) as LContainerNode).data[RENDER_PARENT] ! :
|
||||
currentParent as LElementNode;
|
||||
|
||||
for (let i = 0; i < nodesForSelector.length; i++) {
|
||||
const nodeToProject = nodesForSelector[i];
|
||||
let head = nodeToProject as LTextNode | LElementNode | LContainerNode | null;
|
||||
let tail = nodeToProject as LTextNode | LElementNode | LContainerNode | null;
|
||||
|
||||
if (nodeToProject.tNode.type === TNodeType.Projection) {
|
||||
// Reprojecting a projection -> append the list of previously projected nodes
|
||||
const previouslyProjected = (nodeToProject as LProjectionNode).data;
|
||||
appendToProjectionNode(node, previouslyProjected.head, previouslyProjected.tail);
|
||||
} else {
|
||||
// Projecting a single node
|
||||
appendToProjectionNode(
|
||||
node, nodeToProject as LTextNode | LElementNode | LContainerNode,
|
||||
nodeToProject as LTextNode | LElementNode | LContainerNode);
|
||||
head = previouslyProjected.head;
|
||||
tail = previouslyProjected.tail;
|
||||
}
|
||||
}
|
||||
|
||||
const currentParent = getParentLNode(node);
|
||||
if (canInsertNativeNode(currentParent, viewData)) {
|
||||
ngDevMode && assertNodeOfPossibleTypes(currentParent, TNodeType.Element, TNodeType.View);
|
||||
// process each node in the list of projected nodes:
|
||||
let nodeToProject: LNode|null = node.data.head;
|
||||
const lastNodeToProject = node.data.tail;
|
||||
const renderParent = currentParent.tNode.type === TNodeType.View ?
|
||||
(getParentLNode(currentParent) as LContainerNode).data[RENDER_PARENT] ! :
|
||||
currentParent as LElementNode;
|
||||
addToProjectionList(node, head, tail);
|
||||
|
||||
while (nodeToProject) {
|
||||
appendProjectedNode(
|
||||
nodeToProject as LTextNode | LElementNode | LContainerNode, currentParent, viewData,
|
||||
renderParent);
|
||||
nodeToProject = nodeToProject === lastNodeToProject ? null : nodeToProject.pNextOrParent;
|
||||
if (canInsert) {
|
||||
let currentNode: LNode|null = head;
|
||||
while (currentNode) {
|
||||
appendProjectedNode(
|
||||
currentNode as LTextNode | LElementNode | LContainerNode, currentParent, viewData,
|
||||
renderParent);
|
||||
currentNode = currentNode === tail ? null : currentNode.pNextOrParent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -618,7 +618,7 @@ export function appendProjectedNode(
|
|||
lContainer[RENDER_PARENT] = renderParent;
|
||||
const views = lContainer[VIEWS];
|
||||
for (let i = 0; i < views.length; i++) {
|
||||
addRemoveViewFromContainer(node as LContainerNode, views[i], true, null);
|
||||
addRemoveViewFromContainer(node as LContainerNode, views[i], true, node.native);
|
||||
}
|
||||
}
|
||||
if (node.dynamicLContainerNode) {
|
||||
|
|
|
@ -45,12 +45,15 @@ describe('content projection', () => {
|
|||
});
|
||||
|
||||
it('should project content when root.', () => {
|
||||
/** <ng-content></ng-content> */
|
||||
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
projectionDef(0);
|
||||
projection(1, 0);
|
||||
}
|
||||
});
|
||||
|
||||
/** <child>content</child> */
|
||||
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
elementStart(0, 'child');
|
||||
|
@ -64,6 +67,7 @@ describe('content projection', () => {
|
|||
});
|
||||
|
||||
it('should re-project content when root.', () => {
|
||||
/** <div><ng-content></ng-content></div> */
|
||||
const GrandChild = createComponent('grand-child', function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
projectionDef(0);
|
||||
|
@ -72,6 +76,8 @@ describe('content projection', () => {
|
|||
elementEnd();
|
||||
}
|
||||
});
|
||||
|
||||
/** <grand-child><ng-content></ng-content></grand-child> */
|
||||
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
projectionDef(0);
|
||||
|
@ -80,6 +86,8 @@ describe('content projection', () => {
|
|||
elementEnd();
|
||||
}
|
||||
}, [GrandChild]);
|
||||
|
||||
/** <child><b>Hello</b>World!</child> */
|
||||
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
elementStart(0, 'child');
|
||||
|
@ -137,6 +145,59 @@ describe('content projection', () => {
|
|||
.toEqual('<child><div><projected-comp>content</projected-comp></div></child>');
|
||||
});
|
||||
|
||||
it('should project components that have their own projection', () => {
|
||||
/** <div><ng-content></ng-content></div> */
|
||||
const Child = createComponent('child', (rf: RenderFlags, ctx: any) => {
|
||||
if (rf & RenderFlags.Create) {
|
||||
projectionDef(0);
|
||||
elementStart(1, 'div');
|
||||
{ projection(2, 0); }
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
|
||||
/** <p><ng-content></ng-content></p> */
|
||||
const ProjectedComp = createComponent('projected-comp', (rf: RenderFlags, ctx: any) => {
|
||||
if (rf & RenderFlags.Create) {
|
||||
projectionDef(0);
|
||||
elementStart(1, 'p');
|
||||
projection(2, 0);
|
||||
elementEnd();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* <child>
|
||||
* <projected-comp>
|
||||
* <div> Some content </div>
|
||||
* Other content
|
||||
* </projected-comp>
|
||||
* </child>
|
||||
*/
|
||||
const Parent = createComponent('parent', (rf: RenderFlags, ctx: any) => {
|
||||
if (rf & RenderFlags.Create) {
|
||||
elementStart(0, 'child');
|
||||
{
|
||||
elementStart(1, 'projected-comp');
|
||||
{
|
||||
elementStart(2, 'div');
|
||||
text(3, 'Some content');
|
||||
elementEnd();
|
||||
text(4, 'Other content');
|
||||
}
|
||||
|
||||
elementEnd();
|
||||
}
|
||||
elementEnd();
|
||||
}
|
||||
}, [Child, ProjectedComp]);
|
||||
|
||||
const parent = renderComponent(Parent);
|
||||
expect(toHtml(parent))
|
||||
.toEqual(
|
||||
'<child><div><projected-comp><p><div>Some content</div>Other content</p></projected-comp></div></child>');
|
||||
});
|
||||
|
||||
it('should project content with container.', () => {
|
||||
/** <div> <ng-content></ng-content></div> */
|
||||
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
|
||||
|
@ -366,8 +427,8 @@ describe('content projection', () => {
|
|||
/**
|
||||
* <div>
|
||||
* % if (!skipContent) {
|
||||
* <ng-content></ng-content>
|
||||
* % }
|
||||
* <ng-content></ng-content>
|
||||
* % }
|
||||
* </div>
|
||||
*/
|
||||
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
|
||||
|
@ -414,7 +475,89 @@ describe('content projection', () => {
|
|||
expect(toHtml(parent)).toEqual('<child><div></div></child>');
|
||||
});
|
||||
|
||||
it('should project containers into embedded views', () => {
|
||||
it('should project containers into containers', () => {
|
||||
/**
|
||||
* <div>
|
||||
* Before (inside)
|
||||
* % if (!skipContent) {
|
||||
* <ng-content></ng-content>
|
||||
* % }
|
||||
* After (inside)
|
||||
* </div>
|
||||
*/
|
||||
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
projectionDef(0);
|
||||
elementStart(1, 'div');
|
||||
{
|
||||
text(2, 'Before (inside)-');
|
||||
container(3);
|
||||
text(4, '-After (inside)');
|
||||
}
|
||||
elementEnd();
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
containerRefreshStart(3);
|
||||
{
|
||||
if (!ctx.skipContent) {
|
||||
let rf0 = embeddedViewStart(0);
|
||||
if (rf0 & RenderFlags.Create) {
|
||||
projection(0, 0);
|
||||
}
|
||||
embeddedViewEnd();
|
||||
}
|
||||
}
|
||||
containerRefreshEnd();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* <child>
|
||||
* Before text-
|
||||
* % if (!skipContent) {
|
||||
* content
|
||||
* % }
|
||||
* -After text
|
||||
* </child>
|
||||
*/
|
||||
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
elementStart(0, 'child');
|
||||
{
|
||||
text(1, 'Before text-');
|
||||
container(2);
|
||||
text(3, '-After text');
|
||||
}
|
||||
elementEnd();
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
containerRefreshStart(2);
|
||||
{
|
||||
if (!ctx.skipContent) {
|
||||
let rf0 = embeddedViewStart(0);
|
||||
if (rf0 & RenderFlags.Create) {
|
||||
text(0, 'content');
|
||||
}
|
||||
embeddedViewEnd();
|
||||
}
|
||||
}
|
||||
containerRefreshEnd();
|
||||
}
|
||||
}, [Child]);
|
||||
|
||||
const fixture = new ComponentFixture(Parent);
|
||||
expect(fixture.html)
|
||||
.toEqual(
|
||||
'<child><div>Before (inside)-Before text-content-After text-After (inside)</div></child>');
|
||||
|
||||
fixture.component.skipContent = true;
|
||||
fixture.update();
|
||||
expect(fixture.html)
|
||||
.toEqual(
|
||||
'<child><div>Before (inside)-Before text--After text-After (inside)</div></child>');
|
||||
});
|
||||
|
||||
it('should re-project containers into containers', () => {
|
||||
/**
|
||||
* <div>
|
||||
* % if (!skipContent) {
|
||||
|
@ -446,24 +589,31 @@ describe('content projection', () => {
|
|||
|
||||
/**
|
||||
* <child>
|
||||
* Before text
|
||||
* % if (!skipContent) {
|
||||
* content
|
||||
* <ng-content></ng-content>
|
||||
* % }
|
||||
* -After text
|
||||
* </child>
|
||||
*/
|
||||
const Parent = createComponent('parent', function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
elementStart(0, 'child');
|
||||
{ container(1); }
|
||||
projectionDef(0);
|
||||
elementStart(1, 'child');
|
||||
{
|
||||
text(2, 'Before text');
|
||||
container(3);
|
||||
text(4, '-After text');
|
||||
}
|
||||
elementEnd();
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
containerRefreshStart(1);
|
||||
containerRefreshStart(3);
|
||||
{
|
||||
if (!ctx.skipContent) {
|
||||
let rf0 = embeddedViewStart(0);
|
||||
if (rf0 & RenderFlags.Create) {
|
||||
text(0, 'content');
|
||||
projection(0, 0);
|
||||
}
|
||||
embeddedViewEnd();
|
||||
}
|
||||
|
@ -472,14 +622,33 @@ describe('content projection', () => {
|
|||
}
|
||||
}, [Child]);
|
||||
|
||||
const fixture = new ComponentFixture(Parent);
|
||||
expect(fixture.html).toEqual('<child><div>content</div></child>');
|
||||
let parent: any;
|
||||
/** <parent><p>text</p></parent> */
|
||||
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
elementStart(0, 'parent');
|
||||
{
|
||||
elementStart(1, 'p');
|
||||
{ text(2, 'text'); }
|
||||
elementEnd();
|
||||
}
|
||||
elementEnd();
|
||||
// testing
|
||||
parent = loadDirective(0);
|
||||
}
|
||||
}, [Parent]);
|
||||
|
||||
fixture.component.skipContent = true;
|
||||
const fixture = new ComponentFixture(App);
|
||||
expect(fixture.html)
|
||||
.toEqual('<parent><child><div>Before text<p>text</p>-After text</div></child></parent>');
|
||||
|
||||
parent.skipContent = true;
|
||||
fixture.update();
|
||||
expect(fixture.html).toEqual('<child><div></div></child>');
|
||||
expect(fixture.html)
|
||||
.toEqual('<parent><child><div>Before text-After text</div></child></parent>');
|
||||
});
|
||||
|
||||
|
||||
it('should support projection in embedded views when ng-content is a root node of an embedded view, with other nodes after',
|
||||
() => {
|
||||
let childCmptInstance: any;
|
||||
|
@ -487,8 +656,8 @@ describe('content projection', () => {
|
|||
/**
|
||||
* <div>
|
||||
* % if (!skipContent) {
|
||||
* before-<ng-content></ng-content>-after
|
||||
* % }
|
||||
* before-<ng-content></ng-content>-after
|
||||
* % }
|
||||
* </div>
|
||||
*/
|
||||
const Child = createComponent('child', function(rf: RenderFlags, ctx: any) {
|
||||
|
@ -633,6 +802,129 @@ describe('content projection', () => {
|
|||
expect(toHtml(parent)).toEqual('<child><div>content</div></child>');
|
||||
});
|
||||
|
||||
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) {
|
||||
projectionDef(0);
|
||||
text(1, 'Before');
|
||||
projection(2, 0);
|
||||
text(3, 'After');
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* <projection-comp>
|
||||
* <div>A</div>
|
||||
* <p>123</p>
|
||||
* </projection-comp>
|
||||
* <projection-comp>
|
||||
* <div>B</div>
|
||||
* <p>456</p>
|
||||
* </projection-comp>
|
||||
*/
|
||||
const AppComp = createComponent('app-comp', function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
elementStart(0, 'projection-comp');
|
||||
elementStart(1, 'div');
|
||||
text(2, 'A');
|
||||
elementEnd();
|
||||
elementStart(3, 'p');
|
||||
text(4, '123');
|
||||
elementEnd();
|
||||
elementEnd();
|
||||
elementStart(5, 'projection-comp');
|
||||
elementStart(6, 'div');
|
||||
text(7, 'B');
|
||||
elementEnd();
|
||||
elementStart(8, 'p');
|
||||
text(9, '456');
|
||||
elementEnd();
|
||||
elementEnd();
|
||||
}
|
||||
}, [ProjectionComp]);
|
||||
|
||||
const fixture = new ComponentFixture(AppComp);
|
||||
fixture.update();
|
||||
expect(fixture.html)
|
||||
.toEqual(
|
||||
'<projection-comp>Before<div>A</div><p>123</p>After</projection-comp><projection-comp>Before<div>B</div><p>456</p>After</projection-comp>');
|
||||
});
|
||||
|
||||
it('should re-project with multiple instances of a component with projection', () => {
|
||||
/**
|
||||
* Before
|
||||
* <ng-content></ng-content>
|
||||
* After
|
||||
*/
|
||||
const ProjectionComp = createComponent('projection-comp', function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
projectionDef(0);
|
||||
text(1, 'Before');
|
||||
projection(2, 0);
|
||||
text(3, 'After');
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* <projection-comp>
|
||||
* <div>A</div>
|
||||
* <ng-content></ng-content>
|
||||
* <p>123</p>
|
||||
* </projection-comp>
|
||||
* <projection-comp>
|
||||
* <div>B</div>
|
||||
* <p>456</p>
|
||||
* </projection-comp>
|
||||
*/
|
||||
const ProjectionParent = createComponent('parent-comp', function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
projectionDef(0);
|
||||
elementStart(1, 'projection-comp');
|
||||
elementStart(2, 'div');
|
||||
text(3, 'A');
|
||||
elementEnd();
|
||||
projection(4, 0);
|
||||
elementStart(5, 'p');
|
||||
text(6, '123');
|
||||
elementEnd();
|
||||
elementEnd();
|
||||
elementStart(7, 'projection-comp');
|
||||
elementStart(8, 'div');
|
||||
text(9, 'B');
|
||||
elementEnd();
|
||||
elementStart(10, 'p');
|
||||
text(11, '456');
|
||||
elementEnd();
|
||||
elementEnd();
|
||||
}
|
||||
}, [ProjectionComp]);
|
||||
|
||||
/**
|
||||
* <parent-comp>
|
||||
* **ABC**
|
||||
* </parent-comp>
|
||||
* <parent-comp>
|
||||
* **DEF**
|
||||
* </parent-comp>
|
||||
*/
|
||||
const AppComp = createComponent('app-comp', function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
elementStart(0, 'parent-comp');
|
||||
text(1, '**ABC**');
|
||||
elementEnd();
|
||||
elementStart(2, 'parent-comp');
|
||||
text(3, '**DEF**');
|
||||
elementEnd();
|
||||
}
|
||||
}, [ProjectionParent]);
|
||||
|
||||
const fixture = new ComponentFixture(AppComp);
|
||||
fixture.update();
|
||||
expect(fixture.html)
|
||||
.toEqual(
|
||||
'<parent-comp><projection-comp>Before<div>A</div>**ABC**<p>123</p>After</projection-comp><projection-comp>Before<div>B</div><p>456</p>After</projection-comp></parent-comp><parent-comp><projection-comp>Before<div>A</div>**DEF**<p>123</p>After</projection-comp><projection-comp>Before<div>B</div><p>456</p>After</projection-comp></parent-comp>');
|
||||
});
|
||||
|
||||
describe('with selectors', () => {
|
||||
|
||||
it('should project nodes using attribute selectors', () => {
|
||||
|
|
|
@ -727,9 +727,12 @@ describe('ViewContainerRef', () => {
|
|||
@Component({
|
||||
selector: 'child-with-view',
|
||||
template: `
|
||||
% if (show) {
|
||||
<ng-content></ng-content>
|
||||
% }`
|
||||
Before (inside)-
|
||||
% if (show) {
|
||||
<ng-content></ng-content>
|
||||
% }
|
||||
After (inside)
|
||||
`
|
||||
})
|
||||
class ChildWithView {
|
||||
show: boolean = true;
|
||||
|
@ -740,10 +743,12 @@ describe('ViewContainerRef', () => {
|
|||
template: (rf: RenderFlags, cmp: ChildWithView) => {
|
||||
if (rf & RenderFlags.Create) {
|
||||
projectionDef(0);
|
||||
container(1);
|
||||
text(1, 'Before (inside)-');
|
||||
container(2);
|
||||
text(3, 'After (inside)');
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
containerRefreshStart(1);
|
||||
containerRefreshStart(2);
|
||||
if (cmp.show) {
|
||||
let rf0 = embeddedViewStart(0);
|
||||
if (rf0 & RenderFlags.Create) {
|
||||
|
@ -764,7 +769,9 @@ describe('ViewContainerRef', () => {
|
|||
<span>{{name}}</span>
|
||||
</ng-template>
|
||||
<child-with-view>
|
||||
Before projected
|
||||
<header vcref [tplRef]="foo" [name]="name">blah</header>
|
||||
After projected
|
||||
</child-with-view>`
|
||||
})
|
||||
class Parent {
|
||||
|
@ -777,15 +784,17 @@ describe('ViewContainerRef', () => {
|
|||
if (rf & RenderFlags.Create) {
|
||||
container(0, embeddedTemplate);
|
||||
elementStart(1, 'child-with-view');
|
||||
elementStart(2, 'header', ['vcref', '']);
|
||||
text(3, 'blah');
|
||||
text(2, 'Before projected');
|
||||
elementStart(3, 'header', ['vcref', '']);
|
||||
text(4, 'blah');
|
||||
elementEnd();
|
||||
text(5, 'After projected-');
|
||||
elementEnd();
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
const tplRef = getOrCreateTemplateRef(getOrCreateNodeInjectorForNode(load(0)));
|
||||
elementProperty(2, 'tplRef', bind(tplRef));
|
||||
elementProperty(2, 'name', bind(cmp.name));
|
||||
elementProperty(3, 'tplRef', bind(tplRef));
|
||||
elementProperty(3, 'name', bind(cmp.name));
|
||||
}
|
||||
},
|
||||
directives: [ChildWithView, DirectiveWithVCRef]
|
||||
|
@ -794,13 +803,14 @@ describe('ViewContainerRef', () => {
|
|||
|
||||
const fixture = new ComponentFixture(Parent);
|
||||
expect(fixture.html)
|
||||
.toEqual('<child-with-view><header vcref="">blah</header></child-with-view>');
|
||||
.toEqual(
|
||||
'<child-with-view>Before (inside)-Before projected<header vcref="">blah</header>After projected-After (inside)</child-with-view>');
|
||||
|
||||
directiveInstance !.vcref.createEmbeddedView(directiveInstance !.tplRef, fixture.component);
|
||||
fixture.update();
|
||||
expect(fixture.html)
|
||||
.toEqual(
|
||||
'<child-with-view><header vcref="">blah</header><span>bar</span></child-with-view>');
|
||||
'<child-with-view>Before (inside)-Before projected<header vcref="">blah</header><span>bar</span>After projected-After (inside)</child-with-view>');
|
||||
});
|
||||
|
||||
describe('with select', () => {
|
||||
|
|
Loading…
Reference in New Issue