Angular CDK Portal:能否将多个Portal挂载到单个PortalOutlet?
Short answer: No, the Angular CDK's built-in PortalOutlet does not support attaching multiple Portals to a single outlet natively.
As you've already discovered by digging into the source code, the core constraint lives in the attach method of the base PortalOutlet implementation (from portals.ts):
attach(portal: Portal<any>): any { if(!portal) { throwNullPortalError(); } if(this.hasAttached()) { throwPortalAlreadyAttachedError(); } if (this._isDisposed) { throwPortalOutletAlreadyDisposedError(); } if (portal instanceof ComponentPortal) { this._attachedPortal = portal; return this.attachComponentPortal(portal); } else if (portal instanceof TemplatePortal) { this._attachedPortal = portal; return this.attachTemplatePortal(portal); } }
Let's break down why this prevents multiple attachments:
- The method first checks
this.hasAttached()— if there's already a Portal attached, it immediately throws an error. - The outlet only maintains a single
_attachedPortalproperty to track the currently attached Portal, with no logic to handle a collection of Portals.
You mentioned that creating multiple PortalOutlets or Overlays (and attaching each Portal separately) isn't ideal for your use case. So here are a couple of alternative approaches to achieve a similar outcome:
1. Use a wrapper ComponentPortal
Create a single "container" component that acts as your Portal, then dynamically load all your target components inside this container. You can use Angular's ComponentFactoryResolver or the newer ViewContainerRef.createComponent API to inject multiple components into the wrapper. This way, you only need to attach one Portal to your outlet, but it renders multiple components internally.
2. Implement a custom multi-portal Outlet
If you need closer alignment with the CDK Portal API, you can create a custom PortalOutlet implementation that extends the base logic to manage a list of attached Portals instead of a single one. You'd need to:
- Replace the
_attachedPortalvariable with an array or set to track multiple Portals - Modify the
attachmethod to skip thehasAttached()check (or adjust it to allow multiple) - Update
detachto handle removing individual Portals or all at once - Adjust
hasAttached()to return true if any Portal is attached
These approaches let you avoid managing multiple separate outlets or overlays while still rendering multiple components through the CDK Portal system.
内容的提问来源于stack exchange,提问作者Munerz

