我试图找到一种在Angular2中动态构建模板的方法。我在想templateRef可能会提供一种方法来做到这一点。但我可能是错的。
I found an example of templateRef being used here.
我在这个例子中看了templateRef。我注意到语法是[ng-for-template]
我也试过[ngForTemplate]
因为我知道最近这已经改变了。
所以目前我有这个:
import {Component, TemplateRef} from 'angular2/core';
@Component({
selector : 'body',
template : `
<template [ngForTemplate]="container">
<div class="container"></div>
</template>
`
})
export class App
{
@ContentChild(TemplateRef) container;
constructor() {}
ngAfterContentInit()
{
console.log(this);
}
}
此示例引发错误:
Can't bind to 'ngForTemplate' since it isn't a known native property
所以首先我想知道。这样做的正确方法是什么? The docs don't provide any examples.
其次,有没有一种方法可以将新模板逻辑添加到我的模板或动态构建模板?应用的结构可以是非常大量的不同结构组合。所以,如果可能的话,我想看看是否有一种方法可以做到这一点,而不需要一个包含大量不同ngIf和ngSwitch语句的巨大模板。
我的问题实际上是关于templateRef的第一部分。但是对第二部分的任何帮助或建议表示赞赏。
答案 0 :(得分:16)
创建自己的模板指令并不难,你必须了解两件主要的事情
TemplateRef
包含<template>
标记ViewContainerRef
持有模板的视图,并允许您将模板中的内容嵌入到视图中。我将使用我尝试解决此问题时的示例issue,我的方法不是最好的,但它可以解释它是如何工作的。
我还要澄清一下,你可以使用任何属性作为模板,即使它们已被内置指令使用(显然这不是一个好主意,但你可以这样做)。
考虑我对ngIfIn
的方法(我的糟糕方法)
<template [ngIfValue]="'make'" [ngIfIn]="obj">
This will print
</template>
<template [ngIfValue]="'notExistingValue'" [ngIfIn]="obj">
This won't print
</template>
我们这里有两个模板,每个模板使用两个输入ngIfIn
和ngIfValue
,所以我需要我的指令通过这两个输入获取模板并获取它们的值,所以它看起来像这样< / p>
@Directive({
selector : '[ngIfIn][ngIfValue]',
inputs : ['ngIfIn', 'ngIfValue']
})
首先,我需要注入上面提到的两个类
constructor(private _vr: ViewContainerRef, private _tr: TemplateRef) {}
我还需要缓存I&#39; m通过输入的值
_value: any;
_obj: any;
// Value passed through <template [ngIfValue]="'...'">
set ngIfValue(value: any) {
this._value = value;
}
// Value passed through <template [ngIfIn]="...">
set ngIfIn(obj: any) {
this._obj = obj;
}
在我的情况下,我依赖于这两个值,我可以在ngOnInit
中使用我的逻辑,但是它会运行一次并且不会监听任何输入中的更改,因此我将逻辑放入ngOnChanges
。请记住,在检查了数据绑定属性之后,在检查了视图和内容子项之前,如果其中至少有一个已更改(从文档中复制并粘贴),则会立即调用ngOnChanges
现在我基本上复制&amp;粘贴NgIf逻辑(不那么复杂,但相似)
// ngOnChanges so this gets re-evaluated when one of the inputs change its value
ngOnChanges(changes) {
if(this._value in this._obj) {
// If the condition is true, we embed our template content (TemplateRef) into the view
this._vr.createEmbeddedView(this._tr);
} else {
// If the condition is false we remove the content of the view
this._vr.clear();
}
}
正如您所看到的那样并不复杂:抓住TemplateRef,抓住ViewContainerRef,做一些逻辑并使用ViewContainerRef将TemplateRef嵌入到视图中。
希望我清楚自己,并且我也明确地使用了它们。这是一个plnkr,我解释了这个例子。
答案 1 :(得分:4)
ngForTemplate
仅受ngFor
<template [ngFor] [ngForOf]="..." [ngForTemplate]="container"
或
<div *ngFor="..." [ngForTemplate]="container"
不在普通模板上。它是NgFor
directive
@Input()
使用TemplateRef
如果您引用了ViewContainerRef
,则可以使用它来标记&#34;标记&#34;模板
constructor(private _viewContainer: ViewContainerRef) { }
ngOnInit() {
this.childView = this._viewContainer.createEmbeddedView(this.templ);
this.childView.setLocal('data', this.data);
}