* NOTE: for performance reasons, the possible actions are inlined within the function instead of * being passed as an argument.
( action: WalkTNodeTreeAction, renderer: Renderer, injector: Injector, parent: RElement | null, lNodeToHandle: RNode | LContainer | LView, tNode: TNode, beforeNode?: RNode | null, parentLView?: LView, )
| 115 | * being passed as an argument. |
| 116 | */ |
| 117 | function applyToElementOrContainer( |
| 118 | action: WalkTNodeTreeAction, |
| 119 | renderer: Renderer, |
| 120 | injector: Injector, |
| 121 | parent: RElement | null, |
| 122 | lNodeToHandle: RNode | LContainer | LView, |
| 123 | tNode: TNode, |
| 124 | beforeNode?: RNode | null, |
| 125 | parentLView?: LView, |
| 126 | ) { |
| 127 | // If this slot was allocated for a text node dynamically created by i18n, the text node itself |
| 128 | // won't be created until i18nApply() in the update block, so this node should be skipped. |
| 129 | // For more info, see "ICU expressions should work inside an ngTemplateOutlet inside an ngFor" |
| 130 | // in `i18n_spec.ts`. |
| 131 | if (lNodeToHandle != null) { |
| 132 | let lContainer: LContainer | undefined; |
| 133 | let isComponent = false; |
| 134 | // We are expecting an RNode, but in the case of a component or LContainer the `RNode` is |
| 135 | // wrapped in an array which needs to be unwrapped. We need to know if it is a component and if |
| 136 | // it has LContainer so that we can process all of those cases appropriately. |
| 137 | if (isLContainer(lNodeToHandle)) { |
| 138 | lContainer = lNodeToHandle; |
| 139 | } else if (isLView(lNodeToHandle)) { |
| 140 | isComponent = true; |
| 141 | ngDevMode && assertDefined(lNodeToHandle[HOST], 'HOST must be defined for a component LView'); |
| 142 | lNodeToHandle = lNodeToHandle[HOST]!; |
| 143 | } |
| 144 | const rNode: RNode = unwrapRNode(lNodeToHandle); |
| 145 | if (action === WalkTNodeTreeAction.Create && parent !== null) { |
| 146 | maybeQueueEnterAnimation(parentLView, parent, tNode, injector); |
| 147 | if (beforeNode == null) { |
| 148 | nativeAppendChild(renderer, parent, rNode); |
| 149 | } else { |
| 150 | nativeInsertBefore(renderer, parent, rNode, beforeNode || null, true); |
| 151 | } |
| 152 | } else if (action === WalkTNodeTreeAction.Insert && parent !== null) { |
| 153 | maybeQueueEnterAnimation(parentLView, parent, tNode, injector); |
| 154 | nativeInsertBefore(renderer, parent, rNode, beforeNode || null, true); |
| 155 | cancelLeavingNodes(tNode, rNode as HTMLElement, parentLView); |
| 156 | } else if (action === WalkTNodeTreeAction.Detach) { |
| 157 | if (parentLView?.[ANIMATIONS]?.leave?.has(tNode.index)) { |
| 158 | trackLeavingNodes(tNode, rNode as HTMLElement, parentLView); |
| 159 | } |
| 160 | reusedNodes.delete(rNode as HTMLElement); |
| 161 | runLeaveAnimationsWithCallback( |
| 162 | parentLView, |
| 163 | tNode, |
| 164 | injector, |
| 165 | (nodeHasLeaveAnimations: boolean) => { |
| 166 | if (reusedNodes.has(rNode as HTMLElement)) { |
| 167 | reusedNodes.delete(rNode as HTMLElement); |
| 168 | return; |
| 169 | } |
| 170 | // the nodeHasLeaveAnimations indicates to the renderer that the element needs to |
| 171 | // be removed synchronously and sets the requireSynchronousElementRemoval flag in |
| 172 | // the renderer. |
| 173 | nativeRemoveNode(renderer, rNode, isComponent, nodeHasLeaveAnimations); |
| 174 | }, |
no test coverage detected