refactor(ivy): insert embedded views immediately (#24629)
PR Close #24629
This commit is contained in:
parent
6e20e0aac8
commit
f229449c67
|
@ -19,16 +19,16 @@ import {EmbeddedViewRef as viewEngine_EmbeddedViewRef, ViewRef as viewEngine_Vie
|
|||
import {Type} from '../type';
|
||||
|
||||
import {assertDefined, assertGreaterThan, assertLessThan} from './assert';
|
||||
import {addToViewTree, assertPreviousIsParent, createLContainer, createLNodeObject, createTNode, getDirectiveInstance, getPreviousOrParentNode, getRenderer, isComponent, renderEmbeddedTemplate, resolveDirective} from './instructions';
|
||||
import {addToViewTree, assertPreviousIsParent, createEmbeddedViewNode, createLContainer, createLNodeObject, createTNode, getDirectiveInstance, getPreviousOrParentNode, getRenderer, isComponent, renderEmbeddedTemplate, resolveDirective} from './instructions';
|
||||
import {VIEWS} from './interfaces/container';
|
||||
import {ComponentTemplate, DirectiveDefInternal} from './interfaces/definition';
|
||||
import {ComponentTemplate, DirectiveDefInternal, RenderFlags} from './interfaces/definition';
|
||||
import {LInjector} from './interfaces/injector';
|
||||
import {AttributeMarker, LContainerNode, LElementNode, LNode, LViewNode, TNodeFlags, TNodeType} from './interfaces/node';
|
||||
import {LQueries, QueryReadType} from './interfaces/query';
|
||||
import {Renderer3} from './interfaces/renderer';
|
||||
import {DIRECTIVES, HOST_NODE, INJECTOR, LViewData, QUERIES, RENDERER, TVIEW, TView} from './interfaces/view';
|
||||
import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert';
|
||||
import {appendChild, detachView, getParentLNode, insertView, removeView} from './node_manipulation';
|
||||
import {addRemoveViewFromContainer, appendChild, detachView, getChildLNode, getParentLNode, insertView, removeView} from './node_manipulation';
|
||||
import {notImplemented, stringify} from './util';
|
||||
import {EmbeddedViewRef, ViewRef} from './view_ref';
|
||||
|
||||
|
@ -631,8 +631,11 @@ class ViewContainerRef implements viewEngine_ViewContainerRef {
|
|||
|
||||
createEmbeddedView<C>(templateRef: viewEngine_TemplateRef<C>, context?: C, index?: number):
|
||||
viewEngine_EmbeddedViewRef<C> {
|
||||
const viewRef = templateRef.createEmbeddedView(context || <any>{});
|
||||
this.insert(viewRef, index);
|
||||
const adjustedIdx = this._adjustIndex(index);
|
||||
const viewRef = (templateRef as TemplateRef<C>)
|
||||
.createEmbeddedView(context || <any>{}, this._lContainerNode, adjustedIdx);
|
||||
(viewRef as EmbeddedViewRef<any>).attachToViewContainerRef(this);
|
||||
this._viewRefs.splice(adjustedIdx, 0, viewRef);
|
||||
return viewRef;
|
||||
}
|
||||
|
||||
|
@ -650,11 +653,15 @@ class ViewContainerRef implements viewEngine_ViewContainerRef {
|
|||
const lViewNode = (viewRef as EmbeddedViewRef<any>)._lViewNode;
|
||||
const adjustedIdx = this._adjustIndex(index);
|
||||
|
||||
(viewRef as EmbeddedViewRef<any>).attachToViewContainerRef(this);
|
||||
|
||||
insertView(this._lContainerNode, lViewNode, adjustedIdx);
|
||||
lViewNode.dynamicParent = this._lContainerNode;
|
||||
insertView(this._lContainerNode, lViewNode, adjustedIdx);
|
||||
const views = this._lContainerNode.data[VIEWS];
|
||||
const beforeNode = adjustedIdx + 1 < views.length ?
|
||||
(getChildLNode(views[adjustedIdx + 1]) !).native :
|
||||
this._lContainerNode.native;
|
||||
addRemoveViewFromContainer(this._lContainerNode, lViewNode, true, beforeNode);
|
||||
|
||||
(viewRef as EmbeddedViewRef<any>).attachToViewContainerRef(this);
|
||||
this._viewRefs.splice(adjustedIdx, 0, viewRef);
|
||||
|
||||
return viewRef;
|
||||
|
@ -724,9 +731,14 @@ class TemplateRef<T> implements viewEngine_TemplateRef<T> {
|
|||
this.elementRef = elementRef;
|
||||
}
|
||||
|
||||
createEmbeddedView(context: T): viewEngine_EmbeddedViewRef<T> {
|
||||
const viewNode =
|
||||
renderEmbeddedTemplate(null, this._tView, context, this._renderer, this._queries);
|
||||
createEmbeddedView(context: T, containerNode?: LContainerNode, index?: number):
|
||||
viewEngine_EmbeddedViewRef<T> {
|
||||
const viewNode = createEmbeddedViewNode(this._tView, context, this._renderer, this._queries);
|
||||
if (containerNode) {
|
||||
viewNode.dynamicParent = containerNode;
|
||||
insertView(containerNode, viewNode, index !);
|
||||
}
|
||||
renderEmbeddedTemplate(viewNode, this._tView, context, RenderFlags.Create);
|
||||
return new EmbeddedViewRef(viewNode, this._tView.template !as ComponentTemplate<T>, context);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
import {assertEqual, assertLessThan} from './assert';
|
||||
import {NO_CHANGE, bindingUpdated, createLNode, getPreviousOrParentNode, getRenderer, getViewData, load} from './instructions';
|
||||
import {RENDER_PARENT} from './interfaces/container';
|
||||
import {LContainerNode, LElementNode, LNode, TNodeType} from './interfaces/node';
|
||||
import {BINDING_INDEX} from './interfaces/view';
|
||||
import {appendChild, createTextNode, getParentLNode, removeChild} from './node_manipulation';
|
||||
|
@ -320,6 +321,7 @@ export function i18nApply(startIndex: number, instructions: I18nInstruction[]):
|
|||
if (removedNode.tNode.type === TNodeType.Container && removedNode.dynamicLContainerNode) {
|
||||
removeChild(parentNode, removedNode.dynamicLContainerNode.native || null, viewData);
|
||||
removedNode.dynamicLContainerNode.tNode.detached = true;
|
||||
removedNode.dynamicLContainerNode.data[RENDER_PARENT] = null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -6,19 +6,22 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import './ng_dev_mode';
|
||||
|
||||
import {Sanitizer} from '../sanitization/security';
|
||||
|
||||
import {assertDefined, assertEqual, assertLessThan, assertNotDefined, assertNotEqual} from './assert';
|
||||
import {throwCyclicDependencyError, throwErrorIfNoChangesMode, throwMultipleComponentError} from './errors';
|
||||
import {executeHooks, executeInitHooks, queueInitHooks, queueLifecycleHooks} from './hooks';
|
||||
import {ACTIVE_INDEX, LContainer, RENDER_PARENT, VIEWS} from './interfaces/container';
|
||||
import {LInjector} from './interfaces/injector';
|
||||
import {AttributeMarker, InitialInputData, InitialInputs, LContainerNode, LElementNode, LNode, LProjectionNode, LTextNode, LViewNode, PropertyAliases, PropertyAliasValue, TAttributes, TContainerNode, TElementNode, TNode, TNodeFlags, TNodeType,} from './interfaces/node';
|
||||
import {CssSelectorList, LProjection, NG_PROJECT_AS_ATTR_NAME} from './interfaces/projection';
|
||||
import {LQueries} from './interfaces/query';
|
||||
import {BINDING_INDEX, CLEANUP, CONTEXT, CurrentMatchesList, DIRECTIVES, FLAGS, HEADER_OFFSET, HOST_NODE, INJECTOR, LViewData, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, RootContext, SANITIZER, TAIL, TVIEW, TView,} from './interfaces/view';
|
||||
import './ng_dev_mode';
|
||||
import {assertNodeType} from './node_assert';
|
||||
import {appendChild, appendProjectedNode, canInsertNativeNode, createTextNode, getChildLNode, getLViewChild, getNextLNode, getParentLNode, insertView, removeChild, removeView} from './node_manipulation';
|
||||
import {BINDING_INDEX, CLEANUP, CONTEXT, CurrentMatchesList, DIRECTIVES, FLAGS, HEADER_OFFSET, HOST_NODE, INJECTOR, LViewData, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, RootContext, SANITIZER, TAIL, TData, TVIEW, TView} from './interfaces/view';
|
||||
|
||||
import {AttributeMarker, TAttributes, LContainerNode, LElementNode, LNode, TNodeType, TNodeFlags, LProjectionNode, LTextNode, LViewNode, TNode, TContainerNode, InitialInputData, InitialInputs, PropertyAliases, PropertyAliasValue, TElementNode,} from './interfaces/node';
|
||||
import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert';
|
||||
import {appendChild, insertView, appendProjectedNode, removeView, canInsertNativeNode, createTextNode, getNextLNode, getChildLNode, getParentLNode, getLViewChild} from './node_manipulation';
|
||||
import {isNodeMatchingSelectorList, matchingSelectorIndex} from './node_selector_matcher';
|
||||
import {ComponentDefInternal, ComponentTemplate, ComponentQuery, DirectiveDefInternal, DirectiveDefListOrFactory, PipeDefListOrFactory, RenderFlags} from './interfaces/definition';
|
||||
import {RComment, RElement, RText, Renderer3, RendererFactory3, ProceduralRenderer3, RendererStyleFlags3, isProceduralRenderer} from './interfaces/renderer';
|
||||
|
@ -463,6 +466,30 @@ export function renderTemplate<T>(
|
|||
return host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for creating the LViewNode of a dynamic embedded view,
|
||||
* either through ViewContainerRef.createEmbeddedView() or TemplateRef.createEmbeddedView().
|
||||
* Such lViewNode will then be renderer with renderEmbeddedTemplate() (see below).
|
||||
*/
|
||||
export function createEmbeddedViewNode<T>(
|
||||
tView: TView, context: T, renderer: Renderer3, queries?: LQueries | null): LViewNode {
|
||||
const _isParent = isParent;
|
||||
const _previousOrParentNode = previousOrParentNode;
|
||||
isParent = true;
|
||||
previousOrParentNode = null !;
|
||||
|
||||
const lView =
|
||||
createLViewData(renderer, tView, context, LViewFlags.CheckAlways, getCurrentSanitizer());
|
||||
if (queries) {
|
||||
lView[QUERIES] = queries.createView();
|
||||
}
|
||||
const viewNode = createLNode(-1, TNodeType.View, null, null, null, lView);
|
||||
|
||||
isParent = _isParent;
|
||||
previousOrParentNode = _previousOrParentNode;
|
||||
return viewNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for rendering embedded views (e.g. dynamically created views)
|
||||
*
|
||||
|
@ -474,27 +501,14 @@ export function renderTemplate<T>(
|
|||
* TView for dynamically created views on their host TNode, which only has one instance.
|
||||
*/
|
||||
export function renderEmbeddedTemplate<T>(
|
||||
viewNode: LViewNode | null, tView: TView, context: T, renderer: Renderer3,
|
||||
queries?: LQueries | null): LViewNode {
|
||||
viewNode: LViewNode, tView: TView, context: T, rf: RenderFlags): LViewNode {
|
||||
const _isParent = isParent;
|
||||
const _previousOrParentNode = previousOrParentNode;
|
||||
let oldView: LViewData;
|
||||
let rf: RenderFlags = RenderFlags.Update;
|
||||
try {
|
||||
isParent = true;
|
||||
previousOrParentNode = null !;
|
||||
|
||||
if (viewNode == null) {
|
||||
const lView =
|
||||
createLViewData(renderer, tView, context, LViewFlags.CheckAlways, getCurrentSanitizer());
|
||||
|
||||
if (queries) {
|
||||
lView[QUERIES] = queries.createView();
|
||||
}
|
||||
|
||||
viewNode = createLNode(-1, TNodeType.View, null, null, null, lView);
|
||||
rf = RenderFlags.Create;
|
||||
}
|
||||
oldView = enterView(viewNode.data, viewNode);
|
||||
namespaceHTML();
|
||||
tView.template !(rf, context);
|
||||
|
@ -1575,14 +1589,19 @@ function generateInitialInputs(
|
|||
export function createLContainer(
|
||||
parentLNode: LNode, currentView: LViewData, isForViewContainerRef?: boolean): LContainer {
|
||||
ngDevMode && assertDefined(parentLNode, 'containers should have a parent');
|
||||
let renderParent = canInsertNativeNode(parentLNode, currentView) ?
|
||||
parentLNode as LElementNode | LViewNode :
|
||||
null;
|
||||
if (renderParent && renderParent.tNode.type === TNodeType.View) {
|
||||
renderParent = getParentLNode(renderParent as LViewNode) !.data[RENDER_PARENT];
|
||||
}
|
||||
return [
|
||||
isForViewContainerRef ? null : 0, // active index
|
||||
currentView, // parent
|
||||
null, // next
|
||||
null, // queries
|
||||
[], // views
|
||||
canInsertNativeNode(parentLNode, currentView) ? parentLNode as LElementNode :
|
||||
null // renderParent
|
||||
renderParent as LElementNode
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -1697,7 +1716,7 @@ function refreshDynamicEmbeddedViews(lViewData: LViewData) {
|
|||
const dynamicViewData = lViewNode.data;
|
||||
ngDevMode && assertDefined(dynamicViewData[TVIEW], 'TView must be allocated');
|
||||
renderEmbeddedTemplate(
|
||||
lViewNode, dynamicViewData[TVIEW], dynamicViewData[CONTEXT] !, renderer);
|
||||
lViewNode, dynamicViewData[TVIEW], dynamicViewData[CONTEXT] !, RenderFlags.Update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1764,6 +1783,17 @@ export function embeddedViewStart(viewBlockId: number): RenderFlags {
|
|||
enterView(
|
||||
newView, viewNode = createLNode(viewBlockId, TNodeType.View, null, null, null, newView));
|
||||
}
|
||||
const containerNode = getParentLNode(viewNode) as LContainerNode;
|
||||
if (containerNode) {
|
||||
ngDevMode && assertNodeType(viewNode, TNodeType.View);
|
||||
ngDevMode && assertNodeType(containerNode, TNodeType.Container);
|
||||
const lContainer = containerNode.data;
|
||||
if (creationMode) {
|
||||
// it is a new view, insert it into collection of views for a given container
|
||||
insertView(containerNode, viewNode, lContainer[ACTIVE_INDEX] !);
|
||||
}
|
||||
lContainer[ACTIVE_INDEX] !++;
|
||||
}
|
||||
return getRenderFlags(viewNode.data);
|
||||
}
|
||||
|
||||
|
@ -1794,22 +1824,17 @@ function getOrCreateEmbeddedTView(viewIndex: number, parent: LContainerNode): TV
|
|||
export function embeddedViewEnd(): void {
|
||||
refreshView();
|
||||
isParent = false;
|
||||
const viewNode = previousOrParentNode = viewData[HOST_NODE] as LViewNode;
|
||||
const containerNode = getParentLNode(previousOrParentNode) as LContainerNode;
|
||||
if (containerNode) {
|
||||
ngDevMode && assertNodeType(viewNode, TNodeType.View);
|
||||
ngDevMode && assertNodeType(containerNode, TNodeType.Container);
|
||||
const lContainer = containerNode.data;
|
||||
|
||||
if (creationMode) {
|
||||
previousOrParentNode = viewData[HOST_NODE] as LViewNode;
|
||||
if (creationMode) {
|
||||
const containerNode = getParentLNode(previousOrParentNode) as LContainerNode;
|
||||
if (containerNode) {
|
||||
ngDevMode && assertNodeType(previousOrParentNode, TNodeType.View);
|
||||
ngDevMode && assertNodeType(containerNode, TNodeType.Container);
|
||||
// When projected nodes are going to be inserted, the renderParent of the dynamic container
|
||||
// used by the ViewContainerRef must be set.
|
||||
setRenderParentInProjectedNodes(lContainer[RENDER_PARENT], viewNode);
|
||||
// it is a new view, insert it into collection of views for a given container
|
||||
insertView(containerNode, viewNode, lContainer[ACTIVE_INDEX] !);
|
||||
setRenderParentInProjectedNodes(
|
||||
containerNode.data[RENDER_PARENT], previousOrParentNode as LViewNode);
|
||||
}
|
||||
|
||||
lContainer[ACTIVE_INDEX] !++;
|
||||
}
|
||||
leaveView(viewData[PARENT] !);
|
||||
ngDevMode && assertEqual(isParent, false, 'isParent');
|
||||
|
@ -2002,7 +2027,7 @@ export function projection(
|
|||
|
||||
const currentParent = getParentLNode(node);
|
||||
if (canInsertNativeNode(currentParent, viewData)) {
|
||||
ngDevMode && assertNodeType(currentParent, TNodeType.Element);
|
||||
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;
|
||||
|
|
|
@ -12,7 +12,7 @@ import {LContainerNode, LElementNode, LNode, LProjectionNode, LTextNode, LViewNo
|
|||
import {unusedValueExportToPlacateAjd as unused3} from './interfaces/projection';
|
||||
import {ProceduralRenderer3, RComment, RElement, RNode, RText, Renderer3, isProceduralRenderer, unusedValueExportToPlacateAjd as unused4} from './interfaces/renderer';
|
||||
import {CLEANUP, DIRECTIVES, FLAGS, HEADER_OFFSET, HOST_NODE, HookData, LViewData, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, TVIEW, unusedValueExportToPlacateAjd as unused5} from './interfaces/view';
|
||||
import {assertNodeType} from './node_assert';
|
||||
import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert';
|
||||
import {stringify} from './util';
|
||||
|
||||
const unusedValueToPlacateAjd = unused1 + unused2 + unused3 + unused4 + unused5;
|
||||
|
@ -313,16 +313,6 @@ export function insertView(
|
|||
lView[QUERIES] !.insertView(index);
|
||||
}
|
||||
|
||||
// If the container's renderParent is null, we know that it is a root node of its own parent view
|
||||
// and we should wait until that parent processes its nodes (otherwise, we will insert this view's
|
||||
// nodes twice - once now and once when its parent inserts its views).
|
||||
if (container.data[RENDER_PARENT] !== null && !container.tNode.detached) {
|
||||
// Find the node to insert in front of
|
||||
const beforeNode =
|
||||
index + 1 < views.length ? (getChildLNode(views[index + 1]) !).native : container.native;
|
||||
addRemoveViewFromContainer(container, viewNode, true, beforeNode);
|
||||
}
|
||||
|
||||
// Sets the attached flag
|
||||
viewNode.data[FLAGS] |= LViewFlags.Attached;
|
||||
|
||||
|
@ -485,27 +475,66 @@ function executePipeOnDestroys(viewData: LViewData): void {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns whether a native element should be inserted in the given parent.
|
||||
* Returns whether a native element can be inserted into the given parent.
|
||||
*
|
||||
* There are two reasons why we may not be able to insert a element immediately.
|
||||
* - Projection: When creating a child content element of a component, we have to skip the
|
||||
* insertion because the content of a component will be projected.
|
||||
* `<component><content>delayed due to projection</content></component>`
|
||||
* - Parent container is disconnected: This can happen when we are inserting a view into
|
||||
* parent container, which itself is disconnected. For example the parent container is part
|
||||
* of a View which has not be inserted or is mare for projection but has not been inserted
|
||||
* into destination.
|
||||
*
|
||||
* The native node can be inserted when its parent is:
|
||||
* - A regular element => Yes
|
||||
* - A component host element =>
|
||||
* - if the `currentView` === the parent `view`: The element is in the content (vs the
|
||||
* template)
|
||||
* => don't add as the parent component will project if needed.
|
||||
* - `currentView` !== the parent `view` => The element is in the template (vs the content),
|
||||
* add it
|
||||
* - View element => delay insertion, will be done on `viewEnd()`
|
||||
|
||||
*
|
||||
* @param parent The parent in which to insert the child
|
||||
* @param currentView The LView being processed
|
||||
* @return boolean Whether the child element should be inserted.
|
||||
* @param parent The parent where the child will be inserted into.
|
||||
* @param currentView Current LView being processed.
|
||||
* @return boolean Whether the child should be inserted now (or delayed until later).
|
||||
*/
|
||||
export function canInsertNativeNode(parent: LNode, currentView: LViewData): boolean {
|
||||
const parentIsElement = parent.tNode.type === TNodeType.Element;
|
||||
// We can only insert into a Component or View. Any other type should be an Error.
|
||||
ngDevMode && assertNodeOfPossibleTypes(parent, TNodeType.Element, TNodeType.View);
|
||||
|
||||
return parentIsElement &&
|
||||
(parent.view !== currentView || parent.data === null /* Regular Element. */);
|
||||
if (parent.tNode.type === TNodeType.Element) {
|
||||
// Parent is an element.
|
||||
if (parent.view !== currentView) {
|
||||
// If the Parent view is not the same as current view than we are inserting across
|
||||
// Views. This happens when we insert a root element of the component view into
|
||||
// the component host element and it should always be eager.
|
||||
return true;
|
||||
}
|
||||
// Parent elements can be a component which may have projection.
|
||||
if (parent.data === null) {
|
||||
// Parent is a regular non-component element. We should eagerly insert into it
|
||||
// since we know that this relationship will never be broken.
|
||||
return true;
|
||||
} else {
|
||||
// Parent is a Component. Component's content nodes are not inserted immediately
|
||||
// because they will be projected, and so doing insert at this point would be wasteful.
|
||||
// Since the projection would than move it to its final destination.
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Parent is a View.
|
||||
ngDevMode && assertNodeType(parent, TNodeType.View);
|
||||
|
||||
// Because we are inserting into a `View` the `View` may be disconnected.
|
||||
const grandParentContainer = getParentLNode(parent) as LContainerNode;
|
||||
if (grandParentContainer == null) {
|
||||
// The `View` is not inserted into a `Container` we have to delay insertion.
|
||||
return false;
|
||||
}
|
||||
ngDevMode && assertNodeType(grandParentContainer, TNodeType.Container);
|
||||
if (grandParentContainer.data[RENDER_PARENT] == null) {
|
||||
// The parent `Container` itself is disconnected. So we have to delay.
|
||||
return false;
|
||||
} else {
|
||||
// The parent `Container` is in inserted state, so we can eagerly insert into
|
||||
// this location.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -520,10 +549,21 @@ export function canInsertNativeNode(parent: LNode, currentView: LViewData): bool
|
|||
*/
|
||||
export function appendChild(parent: LNode, child: RNode | null, currentView: LViewData): boolean {
|
||||
if (child !== null && canInsertNativeNode(parent, currentView)) {
|
||||
// We only add the element if not in View or not projected.
|
||||
const renderer = currentView[RENDERER];
|
||||
isProceduralRenderer(renderer) ? renderer.appendChild(parent.native !as RElement, child) :
|
||||
parent.native !.appendChild(child);
|
||||
if (parent.tNode.type === TNodeType.View) {
|
||||
const container = getParentLNode(parent) as LContainerNode;
|
||||
const renderParent = container.data[RENDER_PARENT];
|
||||
const views = container.data[VIEWS];
|
||||
const index = views.indexOf(parent as LViewNode);
|
||||
const beforeNode =
|
||||
index + 1 < views.length ? (getChildLNode(views[index + 1]) !).native : container.native;
|
||||
isProceduralRenderer(renderer) ?
|
||||
renderer.insertBefore(renderParent !.native, child, beforeNode) :
|
||||
renderParent !.native.insertBefore(child, beforeNode, true);
|
||||
} else {
|
||||
isProceduralRenderer(renderer) ? renderer.appendChild(parent.native !as RElement, child) :
|
||||
parent.native !.appendChild(child);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -57,10 +57,10 @@
|
|||
"name": "RENDERER"
|
||||
},
|
||||
{
|
||||
"name": "ROOT_DIRECTIVE_INDICES"
|
||||
"name": "RENDER_PARENT"
|
||||
},
|
||||
{
|
||||
"name": "SANITIZER"
|
||||
"name": "ROOT_DIRECTIVE_INDICES"
|
||||
},
|
||||
{
|
||||
"name": "TVIEW"
|
||||
|
@ -156,7 +156,7 @@
|
|||
"name": "firstTemplatePass"
|
||||
},
|
||||
{
|
||||
"name": "getCurrentSanitizer"
|
||||
"name": "getChildLNode"
|
||||
},
|
||||
{
|
||||
"name": "getDirectiveInstance"
|
||||
|
|
|
@ -83,6 +83,9 @@
|
|||
{
|
||||
"name": "RENDERER"
|
||||
},
|
||||
{
|
||||
"name": "RENDER_PARENT"
|
||||
},
|
||||
{
|
||||
"name": "ROOT_DIRECTIVE_INDICES"
|
||||
},
|
||||
|
@ -335,6 +338,9 @@
|
|||
{
|
||||
"name": "generatePropertyAliases"
|
||||
},
|
||||
{
|
||||
"name": "getChildLNode"
|
||||
},
|
||||
{
|
||||
"name": "getCleanup"
|
||||
},
|
||||
|
|
|
@ -261,6 +261,11 @@ describe('ViewContainerRef', () => {
|
|||
|
||||
insertTpl(ctx: {}) { this._vcRef.createEmbeddedView(this._tplRef, ctx); }
|
||||
|
||||
insertTpl2(ctx: {}) {
|
||||
const viewRef = this._tplRef.createEmbeddedView(ctx);
|
||||
this._vcRef.insert(viewRef);
|
||||
}
|
||||
|
||||
remove(index?: number) { this._vcRef.remove(index); }
|
||||
}
|
||||
|
||||
|
@ -327,7 +332,7 @@ describe('ViewContainerRef', () => {
|
|||
fixture.update();
|
||||
expect(fixture.html).toEqual('before|A|after');
|
||||
|
||||
directiveInstance !.insertTpl({});
|
||||
directiveInstance !.insertTpl2({});
|
||||
expect(fixture.html).toEqual('before|AA|after');
|
||||
|
||||
fixture.component.condition = true;
|
||||
|
|
Loading…
Reference in New Issue