@@ -17,12 +17,12 @@ import {RendererFactory2} from '../render/api';
17
17
import { Type } from '../type' ;
18
18
19
19
import { 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' ;
26
26
import { ViewRef } from './view_ref' ;
27
27
28
28
export class ComponentFactoryResolver extends viewEngine_ComponentFactoryResolver {
@@ -80,23 +80,28 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
80
80
}
81
81
82
82
create (
83
- parentComponentInjector : Injector , projectableNodes ?: any [ ] [ ] | undefined ,
84
- rootSelectorOrNode ?: any ,
83
+ injector : Injector , projectableNodes ?: any [ ] [ ] | undefined , rootSelectorOrNode ?: any ,
85
84
ngModule ?: viewEngine_NgModuleRef < any > | undefined ) : viewEngine_ComponentRef < T > {
86
- ngDevMode && assertDefined ( ngModule , 'ngModule should always be defined' ) ;
85
+ const isInternalRootView = rootSelectorOrNode === undefined ;
87
86
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 ) ;
90
93
91
94
// The first index of the first selector is the tag name.
92
95
const componentTag = this . componentDef . selectors ! [ 0 ] ! [ 0 ] as string ;
93
96
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 ) ) ;
95
100
96
101
// Create the root view. Uses empty TView and ContentTemplate.
97
102
const rootView : LViewData = createLViewData (
98
103
rendererFactory . createRenderer ( hostNode , this . componentDef . rendererType ) ,
99
- createTView ( - 1 , null , null , null , null ) , null ,
104
+ createTView ( - 1 , null , null , null , null ) , rootContext ,
100
105
this . componentDef . onPush ? LViewFlags . Dirty : LViewFlags . CheckAlways ) ;
101
106
rootView [ INJECTOR ] = ngModule && ngModule . injector || null ;
102
107
@@ -116,14 +121,49 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
116
121
component = baseDirectiveCreate ( 0 , this . componentDef . factory ( ) , this . componentDef ) as T ) ;
117
122
initChangeDetectorIfExisting ( elementNode . nodeInjector , component , elementNode . data ! ) ;
118
123
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 ;
119
155
} finally {
120
156
enterView ( oldView , null ) ;
121
157
if ( rendererFactory . end ) rendererFactory . end ( ) ;
122
158
}
123
159
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 ;
127
167
}
128
168
}
129
169
@@ -159,6 +199,7 @@ export class ComponentRef<T> extends viewEngine_ComponentRef<T> {
159
199
* We might want to think about creating a fake component for the top level? Or overwrite
160
200
* detectChanges with a function that calls tickRootContext? */
161
201
this . hostView = this . changeDetectorRef = new ViewRef ( rootView , instance ) ;
202
+ this . hostView . _lViewNode = createLNode ( - 1 , TNodeType . View , null , null , null , rootView ) ;
162
203
this . injector = injector ;
163
204
this . location = new ElementRef ( hostNode ) ;
164
205
this . componentType = componentType ;
0 commit comments