refactor(core): don’t store view factory in `TemplateRef`
Instead, generate `createEmbeddedView`.
This commit is contained in:
parent
d1035da85c
commit
74ede9aa9b
|
@ -264,7 +264,7 @@ export function main() {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should use a default template if a custom one is null', async(() => {
|
it('should use a default template if a custom one is null', async(() => {
|
||||||
const testTemplate = `<ul><template ngFor let-item [ngForOf]="items"
|
const testTemplate = `<ul><template ngFor let-item [ngForOf]="items"
|
||||||
[ngForTemplate]="contentTpl" let-i="index">{{i}}: {{item}};</template></ul>`;
|
[ngForTemplate]="contentTpl" let-i="index">{{i}}: {{item}};</template></ul>`;
|
||||||
TestBed.overrideComponent(TestComponent, {set: {template: testTemplate}});
|
TestBed.overrideComponent(TestComponent, {set: {template: testTemplate}});
|
||||||
const cutTemplate =
|
const cutTemplate =
|
||||||
|
|
|
@ -73,7 +73,7 @@ export class CompileElement extends CompileNode {
|
||||||
this.instances.set(resolveIdentifierToken(Identifiers.Injector).reference, this.injector);
|
this.instances.set(resolveIdentifierToken(Identifiers.Injector).reference, this.injector);
|
||||||
this.instances.set(
|
this.instances.set(
|
||||||
resolveIdentifierToken(Identifiers.Renderer).reference, o.THIS_EXPR.prop('renderer'));
|
resolveIdentifierToken(Identifiers.Renderer).reference, o.THIS_EXPR.prop('renderer'));
|
||||||
if (this.hasViewContainer || this.hasEmbeddedView) {
|
if (this.hasViewContainer) {
|
||||||
this._createAppElement();
|
this._createAppElement();
|
||||||
}
|
}
|
||||||
if (this.component) {
|
if (this.component) {
|
||||||
|
@ -97,9 +97,7 @@ export class CompileElement extends CompileNode {
|
||||||
this.view.createMethod.addStmt(statement);
|
this.view.createMethod.addStmt(statement);
|
||||||
this.appElement = o.THIS_EXPR.prop(fieldName);
|
this.appElement = o.THIS_EXPR.prop(fieldName);
|
||||||
this.instances.set(resolveIdentifierToken(Identifiers.AppElement).reference, this.appElement);
|
this.instances.set(resolveIdentifierToken(Identifiers.AppElement).reference, this.appElement);
|
||||||
if (this.hasViewContainer) {
|
this.view.appElements.push(this.appElement);
|
||||||
this.view.viewContainerAppElements.push(this.appElement);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _createComponentFactoryResolver() {
|
private _createComponentFactoryResolver() {
|
||||||
|
@ -144,7 +142,7 @@ export class CompileElement extends CompileNode {
|
||||||
if (isPresent(embeddedView)) {
|
if (isPresent(embeddedView)) {
|
||||||
var createTemplateRefExpr =
|
var createTemplateRefExpr =
|
||||||
o.importExpr(resolveIdentifier(Identifiers.TemplateRef_)).instantiate([
|
o.importExpr(resolveIdentifier(Identifiers.TemplateRef_)).instantiate([
|
||||||
this.appElement, this.embeddedView.viewFactory
|
o.THIS_EXPR, o.literal(this.nodeIndex), this.renderNode
|
||||||
]);
|
]);
|
||||||
var provider = new CompileProviderMetadata({
|
var provider = new CompileProviderMetadata({
|
||||||
token: resolveIdentifierToken(Identifiers.TemplateRef),
|
token: resolveIdentifierToken(Identifiers.TemplateRef),
|
||||||
|
|
|
@ -46,7 +46,7 @@ export class CompileView implements NameResolver {
|
||||||
public rootNodes: CompileViewRootNode[] = [];
|
public rootNodes: CompileViewRootNode[] = [];
|
||||||
public lastRenderNode: o.Expression = o.NULL_EXPR;
|
public lastRenderNode: o.Expression = o.NULL_EXPR;
|
||||||
|
|
||||||
public viewContainerAppElements: o.Expression[] = [];
|
public appElements: o.Expression[] = [];
|
||||||
|
|
||||||
public createMethod: CompileMethod;
|
public createMethod: CompileMethod;
|
||||||
public animationBindingsMethod: CompileMethod;
|
public animationBindingsMethod: CompileMethod;
|
||||||
|
|
|
@ -477,7 +477,8 @@ function createViewClass(
|
||||||
new o.ClassMethod('dirtyParentQueriesInternal', [], view.dirtyParentQueriesMethod.finish()),
|
new o.ClassMethod('dirtyParentQueriesInternal', [], view.dirtyParentQueriesMethod.finish()),
|
||||||
new o.ClassMethod('destroyInternal', [], generateDestroyMethod(view)),
|
new o.ClassMethod('destroyInternal', [], generateDestroyMethod(view)),
|
||||||
new o.ClassMethod('detachInternal', [], view.detachMethod.finish()),
|
new o.ClassMethod('detachInternal', [], view.detachMethod.finish()),
|
||||||
generateVisitRootNodesMethod(view), generateVisitProjectableNodesMethod(view)
|
generateVisitRootNodesMethod(view), generateVisitProjectableNodesMethod(view),
|
||||||
|
generateCreateEmbeddedViewsMethod(view)
|
||||||
].filter((method) => method.body.length > 0);
|
].filter((method) => method.body.length > 0);
|
||||||
var superClass = view.genConfig.genDebugInfo ? Identifiers.DebugAppView : Identifiers.AppView;
|
var superClass = view.genConfig.genDebugInfo ? Identifiers.DebugAppView : Identifiers.AppView;
|
||||||
|
|
||||||
|
@ -493,7 +494,7 @@ function createViewClass(
|
||||||
|
|
||||||
function generateDestroyMethod(view: CompileView): o.Statement[] {
|
function generateDestroyMethod(view: CompileView): o.Statement[] {
|
||||||
const stmts: o.Statement[] = [];
|
const stmts: o.Statement[] = [];
|
||||||
view.viewContainerAppElements.forEach(
|
view.appElements.forEach(
|
||||||
(appElement) => { stmts.push(appElement.callMethod('destroyNestedViews', []).toStmt()); });
|
(appElement) => { stmts.push(appElement.callMethod('destroyNestedViews', []).toStmt()); });
|
||||||
view.viewChildren.forEach(
|
view.viewChildren.forEach(
|
||||||
(viewChild) => { stmts.push(viewChild.callMethod('destroy', []).toStmt()); });
|
(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.animationBindingsMethod.finish());
|
||||||
stmts.push(...view.detectChangesInInputsMethod.finish());
|
stmts.push(...view.detectChangesInInputsMethod.finish());
|
||||||
view.viewContainerAppElements.forEach((appElement) => {
|
view.appElements.forEach((appElement) => {
|
||||||
stmts.push(
|
stmts.push(
|
||||||
appElement.callMethod('detectChangesInNestedViews', [DetectChangesVars.throwOnChange])
|
appElement.callMethod('detectChangesInNestedViews', [DetectChangesVars.throwOnChange])
|
||||||
.toStmt());
|
.toStmt());
|
||||||
|
@ -717,3 +718,26 @@ function generateVisitNodesStmts(
|
||||||
});
|
});
|
||||||
return stmts;
|
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]));
|
||||||
|
}
|
||||||
|
|
|
@ -17,9 +17,8 @@ import {ViewType} from './view_type';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An AppElement is created for elements that have a ViewContainerRef,
|
* An AppElement is created for elements that have a ViewContainerRef
|
||||||
* a nested component or a <template> element to keep data around
|
* to keep track of the nested views.
|
||||||
* that is needed for later instantiations.
|
|
||||||
*/
|
*/
|
||||||
export class AppElement {
|
export class AppElement {
|
||||||
public nestedViews: AppView<any>[];
|
public nestedViews: AppView<any>[];
|
||||||
|
|
|
@ -43,15 +43,16 @@ export abstract class TemplateRef<C> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TemplateRef_<C> extends TemplateRef<C> {
|
export class TemplateRef_<C> extends TemplateRef<C> {
|
||||||
constructor(private _appElement: AppElement, private _viewFactory: Function) { super(); }
|
constructor(
|
||||||
|
private _parentView: AppView<any>, private _nodeIndex: number, private _nativeElement: any) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
createEmbeddedView(context: C): EmbeddedViewRef<C> {
|
createEmbeddedView(context: C): EmbeddedViewRef<C> {
|
||||||
var view: AppView<C> = this._viewFactory(
|
const view = this._parentView.createEmbeddedViewInternal(this._nodeIndex);
|
||||||
this._appElement.parentView.viewUtils, this._appElement.parentInjector,
|
|
||||||
this._appElement.parentView, this._appElement.index, this._appElement.nativeElement);
|
|
||||||
view.create(context || <any>{});
|
view.create(context || <any>{});
|
||||||
return view.ref;
|
return view.ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
get elementRef(): ElementRef { return this._appElement.elementRef; }
|
get elementRef(): ElementRef { return new ElementRef(this._nativeElement); }
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,11 @@ export abstract class AppView<T> {
|
||||||
*/
|
*/
|
||||||
createInternal(rootSelectorOrNode: string|any): ComponentRef<any> { return null; }
|
createInternal(rootSelectorOrNode: string|any): ComponentRef<any> { return null; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overwritten by implementations.
|
||||||
|
*/
|
||||||
|
createEmbeddedViewInternal(templateNodeIndex: number): AppView<any> { return null; }
|
||||||
|
|
||||||
init(lastRootNode: any, allNodes: any[], disposables: Function[]) {
|
init(lastRootNode: any, allNodes: any[], disposables: Function[]) {
|
||||||
this.lastRootNode = lastRootNode;
|
this.lastRootNode = lastRootNode;
|
||||||
this.allNodes = allNodes;
|
this.allNodes = allNodes;
|
||||||
|
|
|
@ -92,13 +92,20 @@ class _View_TreeRootComponent0 extends import1.AppView<import3.TreeRootComponent
|
||||||
const parentRenderNode: any = this.renderer.createViewRoot(this.parentElement);
|
const parentRenderNode: any = this.renderer.createViewRoot(this.parentElement);
|
||||||
this._anchor_0 = this.renderer.createTemplateAnchor(parentRenderNode, (null as any));
|
this._anchor_0 = this.renderer.createTemplateAnchor(parentRenderNode, (null as any));
|
||||||
this._appEl_0 = new import2.AppElement(0, (null as any), this, this._anchor_0);
|
this._appEl_0 = new import2.AppElement(0, (null as any), this, this._anchor_0);
|
||||||
this._TemplateRef_0_5 =
|
this._TemplateRef_0_5 = new import11.TemplateRef_(this, 0, this._anchor_0);
|
||||||
new import11.TemplateRef_(this._appEl_0, viewFactory_TreeRootComponent1);
|
|
||||||
this._NgIf_0_6 = new import10.NgIf(this._appEl_0.vcRef, this._TemplateRef_0_5);
|
this._NgIf_0_6 = new import10.NgIf(this._appEl_0.vcRef, this._TemplateRef_0_5);
|
||||||
this._expr_0 = import7.UNINITIALIZED;
|
this._expr_0 = import7.UNINITIALIZED;
|
||||||
this.init([], [this._anchor_0], []);
|
this.init([], [this._anchor_0], []);
|
||||||
return (null as any);
|
return (null as any);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createEmbeddedViewInternal(nodeIndex: number): import1.AppView<any> {
|
||||||
|
if (nodeIndex === 0) {
|
||||||
|
return viewFactory_TreeRootComponent1(
|
||||||
|
this.viewUtils, this.parentInjector, this, 0, this._anchor_0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
injectorGetInternal(token: any, requestNodeIndex: number, notFoundResult: any): any {
|
injectorGetInternal(token: any, requestNodeIndex: number, notFoundResult: any): any {
|
||||||
if (((token === import11.TemplateRef) && (0 === requestNodeIndex))) {
|
if (((token === import11.TemplateRef) && (0 === requestNodeIndex))) {
|
||||||
return this._TemplateRef_0_5;
|
return this._TemplateRef_0_5;
|
||||||
|
|
Loading…
Reference in New Issue