angular/components · error · Error
Cannot attach component portal to outlet without an Applicat
Error message
Cannot attach component portal to outlet without an ApplicationRef.
What it means
BasePortalOutlet/DomPortalOutlet can attach a ComponentPortal only if it has an ApplicationRef (needed to create and run change detection for the component). When the outlet was constructed without an ApplicationRef (only an injector/viewContainerRef) and the portal is a ComponentPortal, this dev-mode check throws.
Source
Thrown at src/cdk/portal/dom-portal-outlet.ts:69
// When the ViewContainerRef is missing, we use the factory to create the component directly
// and then manually attach the view to the application.
if (portal.viewContainerRef) {
const injector = portal.injector || portal.viewContainerRef.injector;
const ngModuleRef = injector.get(NgModuleRef, null, {optional: true}) || undefined;
componentRef = portal.viewContainerRef.createComponent(portal.component, {
index: portal.viewContainerRef.length,
injector,
ngModuleRef,
projectableNodes: portal.projectableNodes || undefined,
bindings: portal.bindings || undefined,
directives: portal.directives || undefined,
});
this.setDisposeFn(() => componentRef.destroy());
} else {
if ((typeof ngDevMode === 'undefined' || ngDevMode) && !this._appRef) {
throw Error('Cannot attach component portal to outlet without an ApplicationRef.');
}
const appRef = this._appRef!;
const elementInjector = portal.injector || this._defaultInjector || Injector.NULL;
const environmentInjector = elementInjector.get(EnvironmentInjector, appRef.injector);
componentRef = createComponent(portal.component, {
elementInjector,
environmentInjector,
projectableNodes: portal.projectableNodes || undefined,
bindings: portal.bindings || undefined,
directives: portal.directives || undefined,
});
appRef.attachView(componentRef.hostView);
this.setDisposeFn(() => {
// Verify that the ApplicationRef has registered views before trying to detach a host view.
// This check also protects the `detachView` from being called on a destroyed ApplicationRef.
if (appRef.viewCount > 0) {View on GitHub (pinned to 0411926e7d)
Solutions
- Pass an ApplicationRef when constructing the outlet: `new DomPortalOutlet(host, injector, injector.get(ApplicationRef), injector.get(DOCUMENT))`
- Attach a TemplatePortal or DomPortal instead if you only need DOM content
- Use a ViewContainerRef-based outlet (CdkPortalOutlet directive) which can create components without ApplicationRef
- Ensure your DI environment resolves ApplicationRef (not outside Angular's injector)
Example fix
// before const outlet = new DomPortalOutlet(hostEl, injector, undefined, document); outlet.attachComponentPortal(new ComponentPortal(MyComp)); // throws // after const appRef = injector.get(ApplicationRef); const outlet = new DomPortalOutlet(hostEl, injector, appRef, document); outlet.attachComponentPortal(new ComponentPortal(MyComp));
Defensive patterns
Strategy: validation
Validate before calling
const appRef = injector.get(ApplicationRef, null);
if (appRef) {
const outlet = new DomPortalOutlet(host, injector, appRef, injector.get(DOCUMENT));
outlet.attachComponentPortal(portal);
} Type guard
function supportsComponentPortals(outlet: DomPortalOutlet): boolean {
return (outlet as unknown as {_appRef?: unknown})._appRef != null;
} Try / catch
try {
outlet.attachComponentPortal(portal);
} catch (e) {
if (e.message.includes('without an ApplicationRef')) {
outlet.attachTemplatePortal(new TemplatePortal(tpl, vcr)); // fallback to template portal
} else { throw e; }
} Prevention
- Always pass ApplicationRef when constructing DomPortalOutlet manually
- Get it via injector.get(ApplicationRef) rather than hardcoding undefined
- If you cannot supply ApplicationRef, restrict the outlet to TemplatePortal/DomPortal
- Prefer CdkPortalOutlet directive or ViewContainerRef.createEmbeddedView for component hosting
When it happens
Trigger: Calling `outlet.attachComponentPortal(portal)` on a DomPortalOutlet constructed as `new DomPortalOutlet(hostEl, injector, null, doc)` (no ApplicationRef), or on a CdkPortalOutlet in a context with no ApplicationRef available.
Common situations: Manually constructing DomPortalOutlet for dynamic UI (tooltips, dialogs) and passing undefined for the ApplicationRef parameter; migrating Angular versions where createComponent requires an EnvironmentInjector/ApplicationRef; using the outlet purely for DOM/Template portals then switching to a ComponentPortal.
Related errors
- expected an instance of PointerFocusTracker to be provided
- expected a reference to the parent menu
- DOM portal content must be attached to a parent node.
- DOM portal content must be attached to a parent node.
- Must provide a portal to attach
AI-assisted analysis of angular/components@0411926e7d (2026-08-31).
Data as JSON: /api/errors/2d209a50351c85b6.
Report an issue: GitHub.