import { Injectable , ViewContainerRef , ComponentFactoryResolver , ApplicationRef , Injector , ComponentFactory } from '@angular/core' ; import { BehaviorSubject , Subscription } from "rxjs" ; import { getSymbolObservable } from "rxjs/symbol/observable" ; import { SpawnReference } from "./interfaces/SpawnReference" ; @ Injectable ( ) export class AFSpawnService { constructor ( private cfr , private appRef , private injector ) { } createComponent ( type , vcr ? , context ? ) { let factory = this . cfr . resolveComponentFactory ( type ) ; let componentRef ; if ( vcr ) { componentRef = vcr . createComponent ( factory ) ; } else { componentRef = factory . create ( this . injector ) ; this . appRef . attachView ( componentRef . hostView ) ; document . body . appendChild ( ( componentRef . hostView as any ) . rootNodes [ 0 ] ) ; } let unsubs = this . _wireOutputs ( factory , componentRef , context ) ; let observableSymbol = getSymbolObservable ( window ) ; let context$ ; if ( context && context [ observableSymbol ] ) { context$ = context ; } else { context$ = new BehaviorSubject ( context ) ; } unsubs . push ( context$ . subscribe ( ( ) => { factory . inputs . forEach ( i => { if ( context [ i . propName ] !== undefined ) { componentRef . instance [ i . propName ] = context [ i . propName ] ; } } ) ; } ) ) ; let detach = ( ) => { if ( ! vcr ) { this . appRef . detachView ( componentRef . hostView ) ; } componentRef . destroy ( ) ; unsubs . map ( u => { if ( ! u . closed ) { u . unsubscribe ( ) ; } } ) ; } ; let next = ( data ) => { if ( context$ == context ) { throw `When passing an observable as a context, you cannot call the \`.next\` function from the result. 
                 If you wish to update the values in your context, send the data through the observable that you 
                 passed in as the context.` ; } context$ . next ( data ) ; } ; return { detach , next , } ; } _wireOutputs ( factory , componentRef , context ) { let unsubs = [ ] ; factory . outputs . forEach ( o => { if ( context [ o . propName ] && context [ o . propName ] instanceof Function ) { unsubs . push ( componentRef . instance [ o . propName ] . subscribe ( context [ o . propName ] ) ) ; } } ) ; return unsubs ; } }