* `applyProjectionRecursive` performs operation on the projection specified by `action` (insert, * detach, destroy) * * Inserting a projection requires us to locate the projected nodes from the parent component. The * complication is that those nodes themselves could be re-projected from their p
( renderer: Renderer, action: WalkTNodeTreeAction, lView: LView, tProjectionNode: TProjectionNode, parentRElement: RElement | null, beforeNode: RNode | null, )
| 991 | * @param beforeNode Before which node the insertions should happen. |
| 992 | */ |
| 993 | function applyProjectionRecursive( |
| 994 | renderer: Renderer, |
| 995 | action: WalkTNodeTreeAction, |
| 996 | lView: LView, |
| 997 | tProjectionNode: TProjectionNode, |
| 998 | parentRElement: RElement | null, |
| 999 | beforeNode: RNode | null, |
| 1000 | ) { |
| 1001 | const componentLView = lView[DECLARATION_COMPONENT_VIEW]; |
| 1002 | const componentNode = componentLView[T_HOST] as TElementNode; |
| 1003 | ngDevMode && |
| 1004 | assertEqual(typeof tProjectionNode.projection, 'number', 'expecting projection index'); |
| 1005 | const nodeToProjectOrRNodes = componentNode.projection![tProjectionNode.projection]!; |
| 1006 | if (Array.isArray(nodeToProjectOrRNodes)) { |
| 1007 | // This should not exist, it is a bit of a hack. When we bootstrap a top level node and we |
| 1008 | // need to support passing projectable nodes, so we cheat and put them in the TNode |
| 1009 | // of the Host TView. (Yes we put instance info at the T Level). We can get away with it |
| 1010 | // because we know that TView is not shared and therefore it will not be a problem. |
| 1011 | // This should be refactored and cleaned up. |
| 1012 | for (let i = 0; i < nodeToProjectOrRNodes.length; i++) { |
| 1013 | const rNode = nodeToProjectOrRNodes[i]; |
| 1014 | applyToElementOrContainer( |
| 1015 | action, |
| 1016 | renderer, |
| 1017 | lView[INJECTOR], |
| 1018 | parentRElement, |
| 1019 | rNode, |
| 1020 | tProjectionNode, |
| 1021 | beforeNode, |
| 1022 | lView, |
| 1023 | ); |
| 1024 | } |
| 1025 | } else { |
| 1026 | let nodeToProject: TNode | null = nodeToProjectOrRNodes; |
| 1027 | const projectedComponentLView = componentLView[PARENT] as LView; |
| 1028 | // If a parent <ng-content> is located within a skip hydration block, |
| 1029 | // annotate an actual node that is being projected with the same flag too. |
| 1030 | if (hasInSkipHydrationBlockFlag(tProjectionNode)) { |
| 1031 | nodeToProject.flags |= TNodeFlags.inSkipHydrationBlock; |
| 1032 | } |
| 1033 | applyNodes( |
| 1034 | renderer, |
| 1035 | action, |
| 1036 | nodeToProject, |
| 1037 | projectedComponentLView, |
| 1038 | parentRElement, |
| 1039 | beforeNode, |
| 1040 | true, |
| 1041 | ); |
| 1042 | } |
| 1043 | } |
| 1044 | |
| 1045 | /** |
| 1046 | * `applyContainer` performs an operation on the container and its views as specified by |
no test coverage detected