Repository navigation
Description
Which @angular/* package(s) are the source of the bug?
core
Is this a regression?
No
Description
After one month chasing this issue. I think I can finally reach it. @AndrewKushnir
Example 1:
link: https://codesandbox.io/p/sandbox/unruffled-dawn-dngll7
Previously, this issue #51157 does show that dynamic component aren't hydrated and his example give 2 instance, because he have bootstrap on app.module.ts and it show 2 instance:

Example 2:
link: https://codesandbox.io/p/sandbox/relaxed-feather-27fv8y?file=/src/app/app.module.ts:1,1
I accident commend on bootstrap row in app.module.ts and it does not show error but give expect answer:

After that I think we fix that issue and case close
Example 3:
link: https://codesandbox.io/p/sandbox/sharp-gagarin-j9ycmg?file=/src/app/app.component.ts:24,14
I still get the flick and it still a really annoy issue. So I decide to reproduce my closest behavior on my production repo. So it little different but basicly same with example 2. Just only one think, I did not accident commend and now it alway render browser instead of reuse variable hydrated from server.
right now I have the same issue with the new reproduce with createComponent function. And I realize that problem come from bootstrap: [AppComponent] is open or not. I think it is important and require because my project instant dead if I commend this.
Please provide a link to a minimal reproduction of the bug
https://codesandbox.io/p/sandbox/sharp-gagarin-j9ycmg?file=/src/app/navbar.component.ts:8,26
Please provide the exception or error you saw
No response
Please provide the environment you discovered this bug in (run ng version)
"dependencies": {
"@angular/animations": "^16.2.0",
"@angular/common": "^16.2.0",
"@angular/compiler": "^16.2.0",
"@angular/core": "^16.2.0",
"@angular/forms": "^16.2.0",
"@angular/platform-browser": "^16.2.0",
"@angular/platform-browser-dynamic": "^16.2.0",
"@angular/platform-server": "^16.2.0",
"@angular/router": "^16.2.0",
"@nguniversal/express-engine": "^16.1.3",
"express": "^4.15.2",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.13.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "^16.1.1",
"@angular/cli": "~16.2.0",
"@angular/compiler-cli": "^16.2.0",
"@nguniversal/builders": "^16.1.2",
"@types/express": "^4.17.0",
"@types/jasmine": "~4.3.0",
"@types/node": "^14.15.0",
"jasmine-core": "~4.6.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.0.0",
"typescript": "~5.0.2"
}
Anything else?
No response

Activity
AndrewKushnir commentedon Aug 28, 2023
@hiepxanh do you see any difference in behavior if you use the
bootstrapApplicationfunction and a standalone component to bootstrap an app?hiepxanh commentedon Aug 29, 2023
Yes I do prepare a standalone version. forgot to mention
https://codesandbox.io/p/github/hiepxanh/angular-hydration-flick/application?workspaceId=d385b77c-499a-43e2-a628-69ac00525375
I do read again about your test and I think maybe the different cause this issue, but the test pass but the app is not
hiepxanh commentedon Aug 29, 2023
I think it still the same https://codesandbox.io/p/github/hiepxanh/angular-hydration-flick/application?file=/src/app/app.component.ts:60,4&workspaceId=d385b77c-499a-43e2-a628-69ac00525375
AndrewKushnir commentedon Aug 29, 2023
@hiepxanh thanks for the reply. I've tried opening the page using the link, but got the
Unable to access this workspaceerror. Could you please try to create a repro using a GitHub repository (same code that you use in CodeSandbox, just in a repository) with the most recent version of Angular, so that we can take a look and try to run it? Please also include a bit more information on what is the expected vs actual behavior, it'd help to speed up the investigation. Thank you.hiepxanh commentedon Aug 29, 2023
Yes I'm using https://github.com/hiepxanh/angular-hydration-flick sorry to meantion that, I though use codesandbox will help you faster :D
hiepxanh commentedon Aug 29, 2023
@AndrewKushnir I also do invite you to that repo for more convenient. You can use main branch as app.module and application branch for standalone version

AndrewKushnir commentedon Aug 29, 2023
@hiepxanh thanks for sharing a repro 👍
I've performed some debugging and found out that the problem was caused by the following code:
<div [innerHTML]="sanitizedContent"></div>. What happens is that Angular hydration finds and hydrates the<div>, but after that theinnerHTMLbinding just overrides everything inside that<div>, removing the content that was server-side rendered.The use of
innerHTMLfalls under the "direct DOM manipulation" category, where Angular doesn't know about the elements being created, thus it's unable to hydrate that segment (see more info about direct DOM manipulation in this guide, theinnerHTMLis listed there too).As a possible solution for dynamic component creation (instead of using
innerHTML), you can consider using the NgComponentOutlet, which would hydrate better.hiepxanh commentedon Aug 30, 2023
great, I already consider ngComponentOutlet and try to achive it and I see that it is undefined too as innerHTML. Since ngComponentOutlet is nothing but just an other way to project content. But I findout that I can achive it with transferState and split render in server and skip on browser. I'm going to create a PR to make a docs about this but I will just create it :D
hiepxanh commentedon Aug 30, 2023
for note purpose, with ElementRef.nativeElement, innerHTML can survive after hydration. After that use check to render only on server can achive that skip flick
to see that example https://github.com/hiepxanh/angular-hydration-flick/tree/application
result will be this

angular-automatic-lock-bot commentedon Sep 30, 2023
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
This action has been performed automatically by a bot.