( nodeIndex: number, selectorIndex: number = 0, attrs?: TAttributes | null, fallbackTemplateFn?: ComponentTemplate<unknown>, fallbackDecls?: number, fallbackVars?: number, )
| 147 | * @codeGenApi |
| 148 | */ |
| 149 | export function ɵɵprojection( |
| 150 | nodeIndex: number, |
| 151 | selectorIndex: number = 0, |
| 152 | attrs?: TAttributes | null, |
| 153 | fallbackTemplateFn?: ComponentTemplate<unknown>, |
| 154 | fallbackDecls?: number, |
| 155 | fallbackVars?: number, |
| 156 | ): void { |
| 157 | const lView = getLView(); |
| 158 | const tView = getTView(); |
| 159 | const fallbackIndex = fallbackTemplateFn ? nodeIndex + 1 : null; |
| 160 | |
| 161 | // Fallback content needs to be declared no matter whether the slot is empty since different |
| 162 | // instances of the component may or may not insert it. Also it needs to be declare *before* |
| 163 | // the projection node in order to work correctly with hydration. |
| 164 | if (fallbackIndex !== null) { |
| 165 | declareNoDirectiveHostTemplate( |
| 166 | lView, |
| 167 | tView, |
| 168 | fallbackIndex, |
| 169 | fallbackTemplateFn!, |
| 170 | fallbackDecls!, |
| 171 | fallbackVars!, |
| 172 | null, |
| 173 | attrs, |
| 174 | ); |
| 175 | } |
| 176 | |
| 177 | const tProjectionNode = getOrCreateTNode( |
| 178 | tView, |
| 179 | HEADER_OFFSET + nodeIndex, |
| 180 | TNodeType.Projection, |
| 181 | null, |
| 182 | attrs || null, |
| 183 | ); |
| 184 | |
| 185 | // We can't use viewData[HOST_NODE] because projection nodes can be nested in embedded views. |
| 186 | if (tProjectionNode.projection === null) { |
| 187 | tProjectionNode.projection = selectorIndex; |
| 188 | } |
| 189 | |
| 190 | // `<ng-content>` has no content. Even if there's fallback |
| 191 | // content, the fallback is shown next to it. |
| 192 | setCurrentTNodeAsNotParent(); |
| 193 | |
| 194 | const hydrationInfo = lView[HYDRATION]; |
| 195 | const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock(); |
| 196 | const componentHostNode = lView[DECLARATION_COMPONENT_VIEW][T_HOST] as TElementNode; |
| 197 | const isEmpty = componentHostNode.projection![tProjectionNode.projection] === null; |
| 198 | |
| 199 | if (isEmpty && fallbackIndex !== null) { |
| 200 | insertFallbackContent(lView, tView, fallbackIndex); |
| 201 | } else if (isNodeCreationMode && !isDetachedByI18n(tProjectionNode)) { |
| 202 | // re-distribution of projectable nodes is stored on a component's view level |
| 203 | applyProjection(tView, lView, tProjectionNode); |
| 204 | } |
| 205 | } |
| 206 |
nothing calls this directly
no test coverage detected