@@ -13,7 +13,7 @@ import {Injector} from '../di/injector';
1313import { ComponentRef as viewEngine_ComponentRef } from '../linker/component_factory' ;
1414import { Sanitizer } from '../sanitization/security' ;
1515
16- import { assertComponentType , assertDefined } from './assert' ;
16+ import { assertComponentType , assertNotNull } from './assert' ;
1717import { queueInitHooks , queueLifecycleHooks } from './hooks' ;
1818import { CLEAN_PROMISE , ROOT_DIRECTIVE_INDICES , _getComponentHostLElementNode , baseDirectiveCreate , createLView , createTView , detectChangesInternal , enterView , executeInitAndContentHooks , getRootView , hostElement , initChangeDetectorIfExisting , leaveView , locateHostElement , setHostBindings } from './instructions' ;
1919import { ComponentDef , ComponentType } from './interfaces/definition' ;
@@ -72,6 +72,31 @@ export interface CreateComponentOptions {
7272}
7373
7474
75+ /**
76+ * Bootstraps a component, then creates and returns a `ComponentRef` for that component.
77+ *
78+ * @param componentType Component to bootstrap
79+ * @param options Optional parameters which control bootstrapping
80+ */
81+ export function createComponentRef < T > (
82+ componentType : ComponentType < T > , opts : CreateComponentOptions ) : viewEngine_ComponentRef < T > {
83+ const component = renderComponent ( componentType , opts ) ;
84+ const hostView = _getComponentHostLElementNode ( component ) . data as LView ;
85+ const hostViewRef = new ViewRef ( hostView , component ) ;
86+ return {
87+ location : { nativeElement : getHostElement ( component ) } ,
88+ injector : opts . injector || NULL_INJECTOR ,
89+ instance : component ,
90+ hostView : hostViewRef ,
91+ changeDetectorRef : hostViewRef ,
92+ componentType : componentType ,
93+ // TODO: implement destroy and onDestroy
94+ destroy : ( ) => { } ,
95+ onDestroy : ( cb : Function ) => { }
96+ } ;
97+ }
98+
99+
75100// TODO: A hack to not pull in the NullInjector from @angular /core.
76101export const NULL_INJECTOR : Injector = {
77102 get : ( token : any , notFoundValue ?: any ) => {
@@ -106,8 +131,12 @@ export function renderComponent<T>(
106131 // The first index of the first selector is the tag name.
107132 const componentTag = componentDef . selectors ! [ 0 ] ! [ 0 ] as string ;
108133 const hostNode = locateHostElement ( rendererFactory , opts . host || componentTag ) ;
109- const rootContext = createRootContext ( opts . scheduler || requestAnimationFrame . bind ( window ) ) ;
110-
134+ const rootContext : RootContext = {
135+ // Incomplete initialization due to circular reference.
136+ component : null ! ,
137+ scheduler : opts . scheduler || requestAnimationFrame . bind ( window ) ,
138+ clean : CLEAN_PROMISE ,
139+ } ;
111140 const rootView : LView = createLView (
112141 rendererFactory . createRenderer ( hostNode , componentDef . rendererType ) ,
113142 createTView ( - 1 , null , null , null ) , rootContext ,
@@ -123,8 +152,8 @@ export function renderComponent<T>(
123152 elementNode = hostElement ( componentTag , hostNode , componentDef , sanitizer ) ;
124153
125154 // Create directive instance with factory() and store at index 0 in directives array
126- rootContext . components . push (
127- component = baseDirectiveCreate ( 0 , componentDef . factory ( ) , componentDef ) as T ) ;
155+ component = rootContext . component =
156+ baseDirectiveCreate ( 0 , componentDef . factory ( ) , componentDef ) as T ;
128157 initChangeDetectorIfExisting ( elementNode . nodeInjector , component , elementNode . data ! ) ;
129158
130159 opts . hostFeatures && opts . hostFeatures . forEach ( ( feature ) => feature ( component , componentDef ) ) ;
@@ -140,14 +169,6 @@ export function renderComponent<T>(
140169 return component ;
141170}
142171
143- export function createRootContext ( scheduler : ( workFn : ( ) => void ) => void ) : RootContext {
144- return {
145- components : [ ] ,
146- scheduler : scheduler ,
147- clean : CLEAN_PROMISE ,
148- } ;
149- }
150-
151172/**
152173 * Used to enable lifecycle hooks on the root component.
153174 *
@@ -177,7 +198,7 @@ export function LifecycleHooksFeature(component: any, def: ComponentDef<any>): v
177198 */
178199function getRootContext ( component : any ) : RootContext {
179200 const rootContext = getRootView ( component ) . context as RootContext ;
180- ngDevMode && assertDefined ( rootContext , 'rootContext' ) ;
201+ ngDevMode && assertNotNull ( rootContext , 'rootContext' ) ;
181202 return rootContext ;
182203}
183204
0 commit comments