diff --git a/modules/@angular/common/test/directives/ng_for_spec.ts b/modules/@angular/common/test/directives/ng_for_spec.ts
index b5c209b8c9..5930ae10cf 100644
--- a/modules/@angular/common/test/directives/ng_for_spec.ts
+++ b/modules/@angular/common/test/directives/ng_for_spec.ts
@@ -264,7 +264,7 @@ export function main() {
}));
it('should use a default template if a custom one is null', async(() => {
- const testTemplate = `
`;
TestBed.overrideComponent(TestComponent, {set: {template: testTemplate}});
const cutTemplate =
diff --git a/modules/@angular/compiler/src/view_compiler/compile_element.ts b/modules/@angular/compiler/src/view_compiler/compile_element.ts
index 936e029d0f..b0085dfc88 100644
--- a/modules/@angular/compiler/src/view_compiler/compile_element.ts
+++ b/modules/@angular/compiler/src/view_compiler/compile_element.ts
@@ -73,7 +73,7 @@ export class CompileElement extends CompileNode {
this.instances.set(resolveIdentifierToken(Identifiers.Injector).reference, this.injector);
this.instances.set(
resolveIdentifierToken(Identifiers.Renderer).reference, o.THIS_EXPR.prop('renderer'));
- if (this.hasViewContainer || this.hasEmbeddedView) {
+ if (this.hasViewContainer) {
this._createAppElement();
}
if (this.component) {
@@ -97,9 +97,7 @@ export class CompileElement extends CompileNode {
this.view.createMethod.addStmt(statement);
this.appElement = o.THIS_EXPR.prop(fieldName);
this.instances.set(resolveIdentifierToken(Identifiers.AppElement).reference, this.appElement);
- if (this.hasViewContainer) {
- this.view.viewContainerAppElements.push(this.appElement);
- }
+ this.view.appElements.push(this.appElement);
}
private _createComponentFactoryResolver() {
@@ -144,7 +142,7 @@ export class CompileElement extends CompileNode {
if (isPresent(embeddedView)) {
var createTemplateRefExpr =
o.importExpr(resolveIdentifier(Identifiers.TemplateRef_)).instantiate([
- this.appElement, this.embeddedView.viewFactory
+ o.THIS_EXPR, o.literal(this.nodeIndex), this.renderNode
]);
var provider = new CompileProviderMetadata({
token: resolveIdentifierToken(Identifiers.TemplateRef),
diff --git a/modules/@angular/compiler/src/view_compiler/compile_view.ts b/modules/@angular/compiler/src/view_compiler/compile_view.ts
index 863197ab42..9dcd3ae30f 100644
--- a/modules/@angular/compiler/src/view_compiler/compile_view.ts
+++ b/modules/@angular/compiler/src/view_compiler/compile_view.ts
@@ -46,7 +46,7 @@ export class CompileView implements NameResolver {
public rootNodes: CompileViewRootNode[] = [];
public lastRenderNode: o.Expression = o.NULL_EXPR;
- public viewContainerAppElements: o.Expression[] = [];
+ public appElements: o.Expression[] = [];
public createMethod: CompileMethod;
public animationBindingsMethod: CompileMethod;
diff --git a/modules/@angular/compiler/src/view_compiler/view_builder.ts b/modules/@angular/compiler/src/view_compiler/view_builder.ts
index 2ea9f76281..14d3181b75 100644
--- a/modules/@angular/compiler/src/view_compiler/view_builder.ts
+++ b/modules/@angular/compiler/src/view_compiler/view_builder.ts
@@ -477,7 +477,8 @@ function createViewClass(
new o.ClassMethod('dirtyParentQueriesInternal', [], view.dirtyParentQueriesMethod.finish()),
new o.ClassMethod('destroyInternal', [], generateDestroyMethod(view)),
new o.ClassMethod('detachInternal', [], view.detachMethod.finish()),
- generateVisitRootNodesMethod(view), generateVisitProjectableNodesMethod(view)
+ generateVisitRootNodesMethod(view), generateVisitProjectableNodesMethod(view),
+ generateCreateEmbeddedViewsMethod(view)
].filter((method) => method.body.length > 0);
var superClass = view.genConfig.genDebugInfo ? Identifiers.DebugAppView : Identifiers.AppView;
@@ -493,7 +494,7 @@ function createViewClass(
function generateDestroyMethod(view: CompileView): o.Statement[] {
const stmts: o.Statement[] = [];
- view.viewContainerAppElements.forEach(
+ view.appElements.forEach(
(appElement) => { stmts.push(appElement.callMethod('destroyNestedViews', []).toStmt()); });
view.viewChildren.forEach(
(viewChild) => { stmts.push(viewChild.callMethod('destroy', []).toStmt()); });
@@ -599,7 +600,7 @@ function generateDetectChangesMethod(view: CompileView): o.Statement[] {
}
stmts.push(...view.animationBindingsMethod.finish());
stmts.push(...view.detectChangesInInputsMethod.finish());
- view.viewContainerAppElements.forEach((appElement) => {
+ view.appElements.forEach((appElement) => {
stmts.push(
appElement.callMethod('detectChangesInNestedViews', [DetectChangesVars.throwOnChange])
.toStmt());
@@ -717,3 +718,26 @@ function generateVisitNodesStmts(
});
return stmts;
}
+
+function generateCreateEmbeddedViewsMethod(view: CompileView) {
+ const nodeIndexVar = o.variable('nodeIndex');
+ const stmts: o.Statement[] = [];
+ view.nodes.forEach((node) => {
+ if (node instanceof CompileElement) {
+ if (node.embeddedView) {
+ const parentNodeIndex = node.isRootElement() ? null : node.parent.nodeIndex;
+ stmts.push(new o.IfStmt(
+ nodeIndexVar.equals(o.literal(node.nodeIndex)),
+ [new o.ReturnStatement(node.embeddedView.viewFactory.callFn([
+ ViewProperties.viewUtils,
+ o.THIS_EXPR.callMethod('injector', [o.literal(parentNodeIndex)]), o.THIS_EXPR,
+ o.literal(node.nodeIndex), node.renderNode
+ ]))]));
+ }
+ }
+ });
+ stmts.push(new o.ReturnStatement(o.NULL_EXPR));
+ return new o.ClassMethod(
+ 'createEmbeddedViewInternal', [new o.FnParam(nodeIndexVar.name, o.NUMBER_TYPE)], stmts,
+ o.importType(resolveIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE]));
+}
diff --git a/modules/@angular/core/src/linker/element.ts b/modules/@angular/core/src/linker/element.ts
index 08ea8a022d..ce1f6bb181 100644
--- a/modules/@angular/core/src/linker/element.ts
+++ b/modules/@angular/core/src/linker/element.ts
@@ -17,9 +17,8 @@ import {ViewType} from './view_type';
/**
- * An AppElement is created for elements that have a ViewContainerRef,
- * a nested component or a element to keep data around
- * that is needed for later instantiations.
+ * An AppElement is created for elements that have a ViewContainerRef
+ * to keep track of the nested views.
*/
export class AppElement {
public nestedViews: AppView[];
diff --git a/modules/@angular/core/src/linker/template_ref.ts b/modules/@angular/core/src/linker/template_ref.ts
index 4964105e61..9004d88687 100644
--- a/modules/@angular/core/src/linker/template_ref.ts
+++ b/modules/@angular/core/src/linker/template_ref.ts
@@ -43,15 +43,16 @@ export abstract class TemplateRef {
}
export class TemplateRef_ extends TemplateRef {
- constructor(private _appElement: AppElement, private _viewFactory: Function) { super(); }
+ constructor(
+ private _parentView: AppView, private _nodeIndex: number, private _nativeElement: any) {
+ super();
+ }
createEmbeddedView(context: C): EmbeddedViewRef {
- var view: AppView = this._viewFactory(
- this._appElement.parentView.viewUtils, this._appElement.parentInjector,
- this._appElement.parentView, this._appElement.index, this._appElement.nativeElement);
+ const view = this._parentView.createEmbeddedViewInternal(this._nodeIndex);
view.create(context || {});
return view.ref;
}
- get elementRef(): ElementRef { return this._appElement.elementRef; }
+ get elementRef(): ElementRef { return new ElementRef(this._nativeElement); }
}
diff --git a/modules/@angular/core/src/linker/view.ts b/modules/@angular/core/src/linker/view.ts
index 2f52fdc63f..a6419a44e8 100644
--- a/modules/@angular/core/src/linker/view.ts
+++ b/modules/@angular/core/src/linker/view.ts
@@ -88,6 +88,11 @@ export abstract class AppView {
*/
createInternal(rootSelectorOrNode: string|any): ComponentRef { return null; }
+ /**
+ * Overwritten by implementations.
+ */
+ createEmbeddedViewInternal(templateNodeIndex: number): AppView { return null; }
+
init(lastRootNode: any, allNodes: any[], disposables: Function[]) {
this.lastRootNode = lastRootNode;
this.allNodes = allNodes;
diff --git a/modules/benchmarks/src/tree/ng2_static_ftl/tree_root.ngfactory.ts b/modules/benchmarks/src/tree/ng2_static_ftl/tree_root.ngfactory.ts
index f2a78bac2e..b90b89a996 100644
--- a/modules/benchmarks/src/tree/ng2_static_ftl/tree_root.ngfactory.ts
+++ b/modules/benchmarks/src/tree/ng2_static_ftl/tree_root.ngfactory.ts
@@ -92,13 +92,20 @@ class _View_TreeRootComponent0 extends import1.AppView {
+ if (nodeIndex === 0) {
+ return viewFactory_TreeRootComponent1(
+ this.viewUtils, this.parentInjector, this, 0, this._anchor_0);
+ }
+ }
+
injectorGetInternal(token: any, requestNodeIndex: number, notFoundResult: any): any {
if (((token === import11.TemplateRef) && (0 === requestNodeIndex))) {
return this._TemplateRef_0_5;