【问题标题】:Angular reusable templateAngular 可重用模板
【发布时间】:2017-09-06 10:14:03
【问题描述】:

是否可以编写可重复使用的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,但没有描述如何在多个组件之间共享模板。

【问题讨论】:

    标签: angular angular2-template kendo-ui-angular2 angular-template


    【解决方案1】:

    问题是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 指令来渲染模板。

    【讨论】:

    • 嗨。在阅读了您在博客中的一些帖子后,我决定使用我的第二个选项(模板中的自定义控件)。对于一行额外的代码,这似乎很多。我正在寻找更多用于插入模板的设计解决方案。无需编译,因为这将自动完成。无论如何,很棒的帖子。谢谢你。此解决方案是否适用于 AOT?
    • 它应该适用于 AOT。 不需要编译,因为这会自动完成 - 如果你使用 webpack,我猜你写了一个插件来解析模板并插入部分模板,但这可能又不是你想要的
    【解决方案2】:

    解决此问题的另一种方法是使用 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。

    希望这对您有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      • 2018-12-26
      • 2017-04-24
      相关资源
      最近更新 更多