diff --git a/src/cdk/portal/dom-portal-outlet.ts b/src/cdk/portal/dom-portal-outlet.ts index ee20518ad879..58bfc4c6fb09 100644 --- a/src/cdk/portal/dom-portal-outlet.ts +++ b/src/cdk/portal/dom-portal-outlet.ts @@ -22,12 +22,23 @@ import {BasePortalOutlet, ComponentPortal, TemplatePortal, DomPortal} from './po export class DomPortalOutlet extends BasePortalOutlet { private _document: Document; + /** + * @param outletElement Element into which the content is projected. + * @param _componentFactoryResolver Used to resolve the component factory. + * Only required when attaching component portals. + * @param _appRef Reference to the application. Only used in component portals when there + * is no `ViewContainerRef` available. + * @param _defaultInjector Injector to use as a fallback when the portal being attached doesn't + * have one. Only used for component portals. + * @param _document Reference to the document. Used when attaching a DOM portal. Will eventually + * become a required parameter. + */ constructor( /** Element into which the content is projected. */ public outletElement: Element, - private _componentFactoryResolver: ComponentFactoryResolver, - private _appRef: ApplicationRef, - private _defaultInjector: Injector, + private _componentFactoryResolver?: ComponentFactoryResolver, + private _appRef?: ApplicationRef, + private _defaultInjector?: Injector, /** * @deprecated `_document` Parameter to be made required. @@ -45,7 +56,12 @@ export class DomPortalOutlet extends BasePortalOutlet { * @returns Reference to the created component. */ attachComponentPortal(portal: ComponentPortal): ComponentRef { - const resolver = portal.componentFactoryResolver || this._componentFactoryResolver; + const resolver = (portal.componentFactoryResolver || this._componentFactoryResolver)!; + + if ((typeof ngDevMode === 'undefined' || ngDevMode) && !resolver) { + throw Error('Cannot attach component portal to outlet without a ComponentFactoryResolver.'); + } + const componentFactory = resolver.resolveComponentFactory(portal.component); let componentRef: ComponentRef; @@ -62,10 +78,16 @@ export class DomPortalOutlet extends BasePortalOutlet { this.setDisposeFn(() => componentRef.destroy()); } else { - componentRef = componentFactory.create(portal.injector || this._defaultInjector); - this._appRef.attachView(componentRef.hostView); + if ((typeof ngDevMode === 'undefined' || ngDevMode) && !this._appRef) { + throw Error('Cannot attach component portal to outlet without an ApplicationRef.'); + } + + componentRef = componentFactory.create( + portal.injector || this._defaultInjector || Injector.NULL, + ); + this._appRef!.attachView(componentRef.hostView); this.setDisposeFn(() => { - this._appRef.detachView(componentRef.hostView); + this._appRef!.detachView(componentRef.hostView); componentRef.destroy(); }); } diff --git a/tools/public_api_guard/cdk/portal.md b/tools/public_api_guard/cdk/portal.md index 71b106338faf..cd4dd9dc9fd4 100644 --- a/tools/public_api_guard/cdk/portal.md +++ b/tools/public_api_guard/cdk/portal.md @@ -104,7 +104,7 @@ export class DomPortalHost extends DomPortalOutlet { // @public export class DomPortalOutlet extends BasePortalOutlet { constructor( - outletElement: Element, _componentFactoryResolver: ComponentFactoryResolver, _appRef: ApplicationRef, _defaultInjector: Injector, + outletElement: Element, _componentFactoryResolver?: ComponentFactoryResolver | undefined, _appRef?: ApplicationRef | undefined, _defaultInjector?: Injector | undefined, _document?: any); attachComponentPortal(portal: ComponentPortal): ComponentRef; // @deprecated