fix(ivy): ensure element removal triggers host removal animations (#28162)
Prior to this fix Ivy would not execute any animation triggers that exist as host bindings on an element if it is removed by the parent template. PR Close #28162
This commit is contained in:

committed by
Alex Rickabaugh

parent
e172e97e13
commit
5a582a8afd
@ -267,8 +267,10 @@ export abstract class Renderer2 {
|
||||
* Implement this callback to remove a child node from the host element's DOM.
|
||||
* @param parent The parent node.
|
||||
* @param oldChild The child node to remove.
|
||||
* @param isHostElement Optionally signal to the renderer whether this element is a host element
|
||||
* or not
|
||||
*/
|
||||
abstract removeChild(parent: any, oldChild: any): void;
|
||||
abstract removeChild(parent: any, oldChild: any, isHostElement?: boolean): void;
|
||||
/**
|
||||
* Implement this callback to prepare an element to be bootstrapped
|
||||
* as a root element, and return the element instance.
|
||||
|
@ -74,7 +74,7 @@ export interface ProceduralRenderer3 {
|
||||
destroyNode?: ((node: RNode) => void)|null;
|
||||
appendChild(parent: RElement, newChild: RNode): void;
|
||||
insertBefore(parent: RNode, newChild: RNode, refChild: RNode|null): void;
|
||||
removeChild(parent: RElement, oldChild: RNode): void;
|
||||
removeChild(parent: RElement, oldChild: RNode, isHostElement?: boolean): void;
|
||||
selectRootElement(selectorOrNode: string|any): RElement;
|
||||
|
||||
parentNode(node: RNode): RElement|null;
|
||||
|
@ -14,7 +14,7 @@ import {unusedValueExportToPlacateAjd as unused3} from './interfaces/projection'
|
||||
import {ProceduralRenderer3, RComment, RElement, RNode, RText, Renderer3, isProceduralRenderer, unusedValueExportToPlacateAjd as unused4} from './interfaces/renderer';
|
||||
import {CLEANUP, CONTAINER_INDEX, FLAGS, HEADER_OFFSET, HOST_NODE, HookData, LView, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, TVIEW, unusedValueExportToPlacateAjd as unused5} from './interfaces/view';
|
||||
import {assertNodeType} from './node_assert';
|
||||
import {findComponentView, getNativeByTNode, isLContainer, isRootView, readElementValue, renderStringify} from './util';
|
||||
import {findComponentView, getNativeByTNode, isComponent, isLContainer, isRootView, readElementValue, renderStringify} from './util';
|
||||
|
||||
const unusedValueToPlacateAjd = unused1 + unused2 + unused3 + unused4 + unused5;
|
||||
|
||||
@ -84,15 +84,16 @@ function walkTNodeTree(
|
||||
let nextTNode: TNode|null = null;
|
||||
if (tNode.type === TNodeType.Element) {
|
||||
executeNodeAction(
|
||||
action, renderer, renderParent, getNativeByTNode(tNode, currentView), beforeNode);
|
||||
action, renderer, renderParent, getNativeByTNode(tNode, currentView), tNode, beforeNode);
|
||||
const nodeOrContainer = currentView[tNode.index];
|
||||
if (isLContainer(nodeOrContainer)) {
|
||||
// This element has an LContainer, and its comment needs to be handled
|
||||
executeNodeAction(action, renderer, renderParent, nodeOrContainer[NATIVE], beforeNode);
|
||||
executeNodeAction(
|
||||
action, renderer, renderParent, nodeOrContainer[NATIVE], tNode, beforeNode);
|
||||
}
|
||||
} else if (tNode.type === TNodeType.Container) {
|
||||
const lContainer = currentView ![tNode.index] as LContainer;
|
||||
executeNodeAction(action, renderer, renderParent, lContainer[NATIVE], beforeNode);
|
||||
executeNodeAction(action, renderer, renderParent, lContainer[NATIVE], tNode, beforeNode);
|
||||
|
||||
if (lContainer[VIEWS].length) {
|
||||
currentView = lContainer[VIEWS][0];
|
||||
@ -166,11 +167,11 @@ function walkTNodeTree(
|
||||
*/
|
||||
function executeNodeAction(
|
||||
action: WalkTNodeTreeAction, renderer: Renderer3, parent: RElement | null,
|
||||
node: RComment | RElement | RText, beforeNode?: RNode | null) {
|
||||
node: RComment | RElement | RText, tNode: TNode, beforeNode?: RNode | null) {
|
||||
if (action === WalkTNodeTreeAction.Insert) {
|
||||
nativeInsertBefore(renderer, parent !, node, beforeNode || null);
|
||||
} else if (action === WalkTNodeTreeAction.Detach) {
|
||||
nativeRemoveChild(renderer, parent !, node);
|
||||
nativeRemoveChild(renderer, parent !, node, isComponent(tNode));
|
||||
} else if (action === WalkTNodeTreeAction.Destroy) {
|
||||
ngDevMode && ngDevMode.rendererDestroyNode++;
|
||||
(renderer as ProceduralRenderer3).destroyNode !(node);
|
||||
@ -550,8 +551,9 @@ export function nativeInsertBefore(
|
||||
/**
|
||||
* Removes a native child node from a given native parent node.
|
||||
*/
|
||||
export function nativeRemoveChild(renderer: Renderer3, parent: RElement, child: RNode): void {
|
||||
isProceduralRenderer(renderer) ? renderer.removeChild(parent as RElement, child) :
|
||||
export function nativeRemoveChild(
|
||||
renderer: Renderer3, parent: RElement, child: RNode, isHostElement?: boolean): void {
|
||||
isProceduralRenderer(renderer) ? renderer.removeChild(parent as RElement, child, isHostElement) :
|
||||
parent.removeChild(child);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user