fix(ivy): correct position for re-projected containers (#24721)

PR Close #24721
This commit is contained in:
Kara Erickson
2018-06-29 16:44:54 -07:00
committed by Miško Hevery
parent 3553977bd7
commit a294e0dd79
5 changed files with 356 additions and 53 deletions

View File

@ -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;
}

View File

@ -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;
}
}
}
}

View File

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