角度可重用模板

时间:2017-09-06 10:14:03

标签: angular angular2-template kendo-ui-angular2 angular-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>

我发现this threadthis描述了ngTemplateOutlet,但没有找到如何在多个组件之间共享模板。

2 个答案:

答案 0 :(得分:6)

问题是必须编译ng-template。要理解为什么阅读Here is what you need to know about dynamic components in Angular

现在,模板只能立即编译为组件的一部分。因此,您需要使用此模板定义组件,然后您可以使用viewChild或指令访问此模板工厂。 viewChild @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); } } 取决于life-cycle hooks and change detection,因此我采用指令方式。这是伪代码:

NgTemplateProviderComponent

要了解有关使用指令获取templateRef的方法的更多信息,请阅读Here is how to get ViewContainerRef before @ViewChild query is evaluated

然后,您需要访问templateRef组件工厂,创建其实例以获取class SomeComponent { constructor(r: ComponentFactoryResolver, i: Injector) { const f = r.resolveComponentFactory(NgTemplateProviderComponent); const templateRef =f.create(i).instance.t; } }

ngTemplateOutlet

只有这样你才能使用.md-icon-button{ position: absolute; left: 5px; top: 8px; display: block; float: left; } 指令来渲染模板。

答案 1 :(得分:1)

解决此问题的另一种方法是使用 ng-container 来显示您的内容。正如 Max Koretskyi 发布的那样,您可以遵循类指令方法,以使您的组件可在任何模块中重用。但是,如果您只想通过一种简单的方法在需要相同代码时使 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。

希望这对您有所帮助。