@@ -17,12 +17,12 @@ import {RendererFactory2} from '../render/api';
1717import { Type } from '../type' ;
1818
1919import { assertComponentType , assertDefined } from './assert' ;
20- import { createRootContext } from './component' ;
21- import { baseDirectiveCreate , createLViewData , createTView , enterView , hostElement , initChangeDetectorIfExisting , locateHostElement } from './instructions' ;
22- import { ComponentDefInternal , ComponentType } from './interfaces/definition' ;
23- import { LElementNode } from './interfaces/node' ;
24- import { RElement } from './interfaces/renderer' ;
25- import { INJECTOR , LViewData , LViewFlags , RootContext } from './interfaces/view' ;
20+ import { LifecycleHooksFeature , createRootContext } from './component' ;
21+ import { baseDirectiveCreate , createLNode , createLViewData , createTView , elementCreate , enterView , hostElement , initChangeDetectorIfExisting , locateHostElement , renderEmbeddedTemplate } from './instructions' ;
22+ import { ComponentDefInternal , ComponentType , RenderFlags } from './interfaces/definition' ;
23+ import { LElementNode , TNode , TNodeType } from './interfaces/node' ;
24+ import { RElement , domRendererFactory3 } from './interfaces/renderer' ;
25+ import { FLAGS , INJECTOR , LViewData , LViewFlags , RootContext , TVIEW } from './interfaces/view' ;
2626import { ViewRef } from './view_ref' ;
2727
2828export class ComponentFactoryResolver extends viewEngine_ComponentFactoryResolver {
@@ -80,23 +80,28 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
8080 }
8181
8282 create (
83- parentComponentInjector : Injector , projectableNodes ?: any [ ] [ ] | undefined ,
84- rootSelectorOrNode ?: any ,
83+ injector : Injector , projectableNodes ?: any [ ] [ ] | undefined , rootSelectorOrNode ?: any ,
8584 ngModule ?: viewEngine_NgModuleRef < any > | undefined ) : viewEngine_ComponentRef < T > {
86- ngDevMode && assertDefined ( ngModule , 'ngModule should always be defined' ) ;
85+ const isInternalRootView = rootSelectorOrNode === undefined ;
8786
88- const rendererFactory = ngModule ? ngModule . injector . get ( RendererFactory2 ) : document ;
89- const hostNode = locateHostElement ( rendererFactory , rootSelectorOrNode ) ;
87+ const rendererFactory =
88+ ngModule ? ngModule . injector . get ( RendererFactory2 ) : domRendererFactory3 ;
89+ const hostNode = isInternalRootView ?
90+ elementCreate (
91+ this . selector , rendererFactory . createRenderer ( null , this . componentDef . rendererType ) ) :
92+ locateHostElement ( rendererFactory , rootSelectorOrNode ) ;
9093
9194 // The first index of the first selector is the tag name.
9295 const componentTag = this . componentDef . selectors ! [ 0 ] ! [ 0 ] as string ;
9396
94- const rootContext : RootContext = ngModule ! . injector . get ( ROOT_CONTEXT ) ;
97+ const rootContext : RootContext = ngModule && ! isInternalRootView ?
98+ ngModule . injector . get ( ROOT_CONTEXT ) :
99+ createRootContext ( requestAnimationFrame . bind ( window ) ) ;
95100
96101 // Create the root view. Uses empty TView and ContentTemplate.
97102 const rootView : LViewData = createLViewData (
98103 rendererFactory . createRenderer ( hostNode , this . componentDef . rendererType ) ,
99- createTView ( - 1 , null , null , null , null ) , null ,
104+ createTView ( - 1 , null , null , null , null ) , rootContext ,
100105 this . componentDef . onPush ? LViewFlags . Dirty : LViewFlags . CheckAlways ) ;
101106 rootView [ INJECTOR ] = ngModule && ngModule . injector || null ;
102107
@@ -116,14 +121,49 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
116121 component = baseDirectiveCreate ( 0 , this . componentDef . factory ( ) , this . componentDef ) as T ) ;
117122 initChangeDetectorIfExisting ( elementNode . nodeInjector , component , elementNode . data ! ) ;
118123
124+ // TODO: should LifecycleHooksFeature and other host features be generated by the compiler and
125+ // executed here?
126+ // Angular 5 reference: https://stackblitz.com/edit/lifecycle-hooks-vcref
127+ LifecycleHooksFeature ( component , this . componentDef ) ;
128+
129+ // Transform the arrays of native nodes into a LNode structure that can be consumed by the
130+ // projection instruction. This is needed to support the reprojection of these nodes.
131+ if ( projectableNodes ) {
132+ let index = 0 ;
133+ const projection : TNode [ ] = elementNode . tNode . projection = [ ] ;
134+ for ( let i = 0 ; i < projectableNodes . length ; i ++ ) {
135+ const nodeList = projectableNodes [ i ] ;
136+ let firstTNode : TNode | null = null ;
137+ let previousTNode : TNode | null = null ;
138+ for ( let j = 0 ; j < nodeList . length ; j ++ ) {
139+ const lNode =
140+ createLNode ( ++ index , TNodeType . Element , nodeList [ j ] as RElement , null , null ) ;
141+ if ( previousTNode ) {
142+ previousTNode . next = lNode . tNode ;
143+ } else {
144+ firstTNode = lNode . tNode ;
145+ }
146+ previousTNode = lNode . tNode ;
147+ }
148+ projection . push ( firstTNode ! ) ;
149+ }
150+ }
151+
152+ // Execute the template in creation mode only, and then turn off the CreationMode flag
153+ renderEmbeddedTemplate ( elementNode , elementNode . data ! [ TVIEW ] , component , RenderFlags . Create ) ;
154+ elementNode . data ! [ FLAGS ] &= ~ LViewFlags . CreationMode ;
119155 } finally {
120156 enterView ( oldView , null ) ;
121157 if ( rendererFactory . end ) rendererFactory . end ( ) ;
122158 }
123159
124- // TODO(misko): this is the wrong injector here.
125- return new ComponentRef (
126- this . componentType , component , rootView , ngModule ! . injector , hostNode ! ) ;
160+ const componentRef =
161+ new ComponentRef ( this . componentType , component , rootView , injector , hostNode ! ) ;
162+ if ( isInternalRootView ) {
163+ // The host element of the internal root view is attached to the component's host view node
164+ componentRef . hostView . _lViewNode ! . tNode . child = elementNode . tNode ;
165+ }
166+ return componentRef ;
127167 }
128168}
129169
@@ -159,6 +199,7 @@ export class ComponentRef<T> extends viewEngine_ComponentRef<T> {
159199 * We might want to think about creating a fake component for the top level? Or overwrite
160200 * detectChanges with a function that calls tickRootContext? */
161201 this . hostView = this . changeDetectorRef = new ViewRef ( rootView , instance ) ;
202+ this . hostView . _lViewNode = createLNode ( - 1 , TNodeType . View , null , null , null , rootView ) ;
162203 this . injector = injector ;
163204 this . location = new ElementRef ( hostNode ) ;
164205 this . componentType = componentType ;
0 commit comments