import { ComponentPortal , DomPortal , Portal , PortalOutlet } from '@angular/cdk/portal' ; import { ApplicationRef , ComponentFactoryResolver , ComponentRef , EmbeddedViewRef , Injector } from '@angular/core' ; export class DomPortalOutlet implements PortalOutlet { private disposeFn : ( ( ) => void ) | null ; private isDisposed : boolean ; protected attachedPortal : Portal < unknown > ; constructor ( protected outletElement , protected componentFactoryResolver , protected appRef , protected defaultInjector , protected projectableNodes ) { } attach < T > ( portal ) { const resolver = portal . componentFactoryResolver || this . componentFactoryResolver ; const componentFactory = resolver . resolveComponentFactory ( portal . component ) ; let componentRef ; if ( portal . viewContainerRef ) { componentRef = portal . viewContainerRef . createComponent ( componentFactory , portal . viewContainerRef . length , portal . injector || portal . viewContainerRef . injector , this . projectableNodes ) ; this . setDisposeFn ( ( ) => { componentRef . destroy ( ) ; } ) ; } else { componentRef = componentFactory . create ( portal . injector || this . defaultInjector ) ; this . appRef . attachView ( componentRef . hostView ) ; this . setDisposeFn ( ( ) => { this . appRef . detachView ( componentRef . hostView ) ; componentRef . destroy ( ) ; } ) ; } this . outletElement . replaceWith ( this . getComponentRootNode ( componentRef ) ) ; this . attachedPortal = portal ; return componentRef ; } hasAttached ( ) { return ! ! this . attachedPortal ; } /** Detaches a previously attached portal. */ detach ( ) { if ( this . attachedPortal ) { this . attachedPortal . setAttachedHost ( null ) ; this . attachedPortal = null ; } this . invokeDisposeFn ( ) ; } /** Permanently dispose of this portal host. */ dispose ( ) { if ( this . hasAttached ( ) ) { this . detach ( ) ; } this . invokeDisposeFn ( ) ; this . isDisposed = true ; } docs-private setDisposeFn ( fn ) { this . disposeFn = fn ; } private invokeDisposeFn ( ) { if ( this . disposeFn ) { this . disposeFn ( ) ; this . disposeFn = null ; } } /** Gets the root HTMLElement for an instantiated component. */ private getComponentRootNode ( componentRef ) { return ( componentRef . hostView as EmbeddedViewRef < any > ) . rootNodes [ 0 ] as HTMLElement ; } }