diff --git a/packages/core/src/hydration/annotate.ts b/packages/core/src/hydration/annotate.ts index 75258ca04d2..1f9566effe4 100644 --- a/packages/core/src/hydration/annotate.ts +++ b/packages/core/src/hydration/annotate.ts @@ -583,6 +583,12 @@ function conditionallyAnnotateNodePath( lView: LView, excludedParentNodes: Set | null, ) { + if (isProjectionTNode(tNode)) { + // Do not annotate projection nodes (), since + // they don't have a corresponding DOM node representing them. + return; + } + // Handle case #1 described above. if ( tNode.projectionNext && diff --git a/packages/platform-server/test/hydration_spec.ts b/packages/platform-server/test/hydration_spec.ts index 872aacf3e4e..ac25d07ff43 100644 --- a/packages/platform-server/test/hydration_spec.ts +++ b/packages/platform-server/test/hydration_spec.ts @@ -5685,6 +5685,72 @@ describe('platform-server hydration integration', () => { verifyClientAndSSRContentsMatch(ssrContents, clientRootNode); }); + it('should support cases when some element nodes are not projected', async () => { + @Component({ + standalone: true, + selector: 'app-dropdown-content', + template: ``, + }) + class DropdownContentComponent {} + + @Component({ + standalone: true, + selector: 'app-dropdown', + template: ` + @if (false) { + + } + `, + }) + class DropdownComponent {} + + @Component({ + standalone: true, + imports: [DropdownComponent, DropdownContentComponent], + selector: 'app-menu', + template: ` + + + + + + `, + }) + class MenuComponent {} + + @Component({ + selector: 'app', + standalone: true, + imports: [MenuComponent], + template: ` + + Menu Content + + `, + }) + class SimpleComponent {} + + const html = await ssr(SimpleComponent); + const ssrContents = getAppContents(html); + + expect(ssrContents).toContain('(appRef); + appRef.tick(); + + const clientRootNode = compRef.location.nativeElement; + verifyAllNodesClaimedForHydration(clientRootNode); + verifyClientAndSSRContentsMatch(ssrContents, clientRootNode); + }); + it('should support cases when view containers are not projected', async () => { @Component({ standalone: true,