Angular 可重复使用的模板
Angular reusable template
是否可以编写可重用的ng-template
?我的很多组件使用完全相同的 ng-template
.
例如:
<kendo-grid>
<kendo-grid-column field="group">
<ng-template kendoGridEditTemplate let-dataItem="dataItem" let-formGroup="form">
<kendo-dropdownlist #listGroups [data]="groups"
textField="title"
valueField="id"
[valuePrimitive]="true"
[filterable]="true"
[formControl]="form.get('groupId')">
</kendo-dropdownlist>
</ng-template>
</kendo-grid-column>
</kendo-grid>
我不想在我的所有组件中重复这个模板和背后的逻辑。我可以编写自定义组件并将此代码压缩为:
<kendo-grid>
<kendo-grid-column field="group">
<ng-template kendoGridEditTemplate let-dataItem="dataItem" let-formGroup="form">
<my-custom-component [formControl]="form.get('groupId')">
</my-custom-component>
</ng-template>
</kendo-grid-column>
</kendo-grid>
但我想做更多:
<kendo-grid>
<kendo-grid-column field="group">
<ng-template [ngTemplateOutlet]="templateFromAnotherSource">
</ng-template>
</kendo-grid-column>
</kendo-grid>
我发现 and 描述了 ngTemplateOutlet
,但没有描述如何在多个组件之间共享模板。
问题是 ng-template
必须编译。要理解为什么阅读 Here is what you need to know about dynamic components in Angular.
现在,模板现在只能作为组件的一部分进行编译。所以你需要用这个模板定义一个组件,然后你可以使用 viewChild
或指令访问这个模板工厂。使用 viewChild
你依赖于 life-cycle hooks and change detection 所以我会采用指令方法。这是伪代码:
@Component() {
template: '<ng-template requestor>...</ng-template>'
}
class NgTemplateProviderComponent {
t: TemplateRef;
register(t) {
this.t = t;
}
}
@Directive() {
selector: 'requestor;
}
class TemplateRequestor {
constructor(t: TemplateRef, p: NgTemplateProviderComponent) {
p.register(t);
}
}
要了解有关使用指令获取 templateRef 的方法的更多信息,请阅读 Here is how to get ViewContainerRef before @ViewChild query is evaluated。
然后,您需要访问 NgTemplateProviderComponent
组件工厂,创建其实例以获取 templateRef
:
class SomeComponent {
constructor(r: ComponentFactoryResolver, i: Injector) {
const f = r.resolveComponentFactory(NgTemplateProviderComponent);
const templateRef =f.create(i).instance.t;
}
}
然后您才可以使用 ngTemplateOutlet
指令来呈现模板。
解决此问题的另一种方法是使用 ng-container 来显示您的内容。正如 Max Koretskyi 发布的那样,您可以遵循 class 指令方法,以使您的组件可在任何模块中重用。但是,如果您只想通过一种简单的方法使您的 HTML 在需要相同代码时看起来有点难看 (也是 DRY 原则),您可以这样做:
<ng-template #YOUR-NG-TEMPLATE-NAME let-YOUR-PARAMETER="YOUR-PARAMETER">
// Your large implementation
</ng-template>
...
<kendo-grid-column field="whatever">
<ng-template kendoGridEditTemplate let-YOUR-PARAMETER="YOUR-VARIABLE">
<ng-container [ngTemplateOutlet]="YOUR-NG-TEMPLATE-NAME"
[ngTemplateOutletContext]="{ YOUR-PARAMETER: YOUR-PARAMETER }">
</ng-container>
</ng-template>
</kendo-grid-column>
这在需要重用大量代码时很有用,如果您只想显示属性,只需像往常一样使用带有一些 Kendo 指令的 ng-template。
希望对您有所帮助。
是否可以编写可重用的ng-template
?我的很多组件使用完全相同的 ng-template
.
例如:
<kendo-grid>
<kendo-grid-column field="group">
<ng-template kendoGridEditTemplate let-dataItem="dataItem" let-formGroup="form">
<kendo-dropdownlist #listGroups [data]="groups"
textField="title"
valueField="id"
[valuePrimitive]="true"
[filterable]="true"
[formControl]="form.get('groupId')">
</kendo-dropdownlist>
</ng-template>
</kendo-grid-column>
</kendo-grid>
我不想在我的所有组件中重复这个模板和背后的逻辑。我可以编写自定义组件并将此代码压缩为:
<kendo-grid>
<kendo-grid-column field="group">
<ng-template kendoGridEditTemplate let-dataItem="dataItem" let-formGroup="form">
<my-custom-component [formControl]="form.get('groupId')">
</my-custom-component>
</ng-template>
</kendo-grid-column>
</kendo-grid>
但我想做更多:
<kendo-grid>
<kendo-grid-column field="group">
<ng-template [ngTemplateOutlet]="templateFromAnotherSource">
</ng-template>
</kendo-grid-column>
</kendo-grid>
我发现 ngTemplateOutlet
,但没有描述如何在多个组件之间共享模板。
问题是 ng-template
必须编译。要理解为什么阅读 Here is what you need to know about dynamic components in Angular.
现在,模板现在只能作为组件的一部分进行编译。所以你需要用这个模板定义一个组件,然后你可以使用 viewChild
或指令访问这个模板工厂。使用 viewChild
你依赖于 life-cycle hooks and change detection 所以我会采用指令方法。这是伪代码:
@Component() {
template: '<ng-template requestor>...</ng-template>'
}
class NgTemplateProviderComponent {
t: TemplateRef;
register(t) {
this.t = t;
}
}
@Directive() {
selector: 'requestor;
}
class TemplateRequestor {
constructor(t: TemplateRef, p: NgTemplateProviderComponent) {
p.register(t);
}
}
要了解有关使用指令获取 templateRef 的方法的更多信息,请阅读 Here is how to get ViewContainerRef before @ViewChild query is evaluated。
然后,您需要访问 NgTemplateProviderComponent
组件工厂,创建其实例以获取 templateRef
:
class SomeComponent {
constructor(r: ComponentFactoryResolver, i: Injector) {
const f = r.resolveComponentFactory(NgTemplateProviderComponent);
const templateRef =f.create(i).instance.t;
}
}
然后您才可以使用 ngTemplateOutlet
指令来呈现模板。
解决此问题的另一种方法是使用 ng-container 来显示您的内容。正如 Max Koretskyi 发布的那样,您可以遵循 class 指令方法,以使您的组件可在任何模块中重用。但是,如果您只想通过一种简单的方法使您的 HTML 在需要相同代码时看起来有点难看 (也是 DRY 原则),您可以这样做:
<ng-template #YOUR-NG-TEMPLATE-NAME let-YOUR-PARAMETER="YOUR-PARAMETER">
// Your large implementation
</ng-template>
...
<kendo-grid-column field="whatever">
<ng-template kendoGridEditTemplate let-YOUR-PARAMETER="YOUR-VARIABLE">
<ng-container [ngTemplateOutlet]="YOUR-NG-TEMPLATE-NAME"
[ngTemplateOutletContext]="{ YOUR-PARAMETER: YOUR-PARAMETER }">
</ng-container>
</ng-template>
</kendo-grid-column>
这在需要重用大量代码时很有用,如果您只想显示属性,只需像往常一样使用带有一些 Kendo 指令的 ng-template。
希望对您有所帮助。