In my earlier post, A Practical Implementation of Angular's Route Reuse Strategy, I taught a nifty trick: keep components alive between route hops and stop iframes from reloading by hoisting them into a global wrapper.
That solution worked, but it was invasive—whenever the <iframe>
lived inside a third-party component we had to “hack” into it.
React ships with Portals, a magic trapdoor that teleports DOM nodes wherever you fancy.
Good news: Angular has an equivalent in the CDK!
A Portal is a piece of UI that can be dynamically rendered to an open slot on the page.
*(Angular Material CDK docs)
A Portal can be:
- a
Component
- a
TemplateRef
The slot that receives it is a PortalOutlet.
CDK Portals in a Nutshell
Template-driven usage:
htmlCopy code
Programmatic usage:
tsCopy code
The Iframe Problem (Again)
In the new demo repo (now a pnpm monorepo) the details page contains a third-party iframe component:
htmlCopy code
But as soon as we click away, poof—the iframe evaporates and its internal state resets (insert sad trombone 🎺):
Time to let CDK Portals keep the iframe alive—without touching the third-party code.
Designing The Service
Our ThirdPartyIframePortalService
has it own responsibilities:
- Register a single global host container +
CdkPortalOutlet
. - Attach/detach the
ThirdPartyIframe
component via aComponentPortal
. - Mirror the size/position of the “placeholder” element so the user still sees the iframe exactly where it belongs.
- Clean up
ResizeObserver
, component refs, and BehaviorSubjects to avoid memory leaks.
Key implementation points (abridged for clarity):
tsCopy code
ComponentPortal
constructor signature isnew ComponentPortal(Cmp, viewContainerRef?, injector?)
viewContainerRef
affects the logical component tree, while the PortalOutlet
controls where the component renders in the DOM.
Where to Mount the Portal
app.html
htmlCopy code
app.component.ts
tsCopy code
Attaching from the Details Page
task-detail.page.html
htmlCopy code
task-detail.page.ts
tsCopy code
Finally, the iframe component now is like a magician—it’s rendered just once at the application root but performs a clever trick! It visually pops up exactly where you need it and keeps its internal state intact, no matter how many routes you explore. Ta-da!
Cleaning Up When Switching Tasks
Because the iframe now lives at the app root, we must explicitly destroy it when navigating to a different task:
tsCopy code
Conclusion
So what do we get by fusing Route Reuse Strategy with CDK Portals?
- Retain heavy, stateful components (iframes, video players, maps, etc.) across route changes.
- Avoid invasive “global component” hacks—no need to touch the third-party code.
- Keep full control over cleanup to prevent memory leaks.
Give it a try in your own project and enjoy flicker-free iframes!