角度4:带插值的动态模板 [英] Angular 4: Dynamic template with interpolation

查看:70
本文介绍了角度4:带插值的动态模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个数据表组件,该组件被设计为非常通用的组件.

I'm building a data table component that is being designed as very generic component.

想法是将表定义为:

<app-datatable [items]="currentPageResult">
    <app-datatable-column attribute="id"
                          header="ID"></app-datatable-column>
    <app-datatable-column attribute="name"
                          header="First Name"></app-datatable-column>
    <app-datatable-column attribute="last_name"
                          header="Last Name"></app-datatable-column>
</app-datatable>

通过这种方式,我们可以将数组指定到datatable组件中,并且通过定义datatable-columns我们可以决定属性应该显示该表.在内部,表格将按列执行ngFor,而按项目执行另一个ngFor.

In this way, we can specify the array into the datatable component, and by defining datatable-columns we can decide witch attributes should display the table. Internally the table will do an ngFor by columns and another ngFor by items.

这部分很简单,现在工作得很好,当我想将自定义html内容放入td时,事情变得很棘手.像这样:

This part was simple and now it's working very well, the thing becomes tricky when I want custom html content into the td; Something like this:

<app-datatable [items]="currentPageResult">
    <app-datatable-column attribute="id"
                          header="ID"
                          [template]="titleTemplate">
        <ng-template #titleTemplate>
            <a role="button" [routerLink]="[data.id]">
                {{data.id}}
            </a>
        </ng-template>
    </app-datatable-column>
    <app-datatable-column attribute="name"
                          header="First Name"></app-datatable-column>
    <app-datatable-column attribute="last_name"
                          header="Last Name"></app-datatable-column>
</app-datatable>

请注意,我正在使用data作为迭代变量,但是它实际上不起作用,我只是在说明我想做的事情.

Notice that i'm using data as the iteration variable, but it actually doesn't work, I'm just illustrating what I want to do.

为解决此问题,我使用了'$ data'作为asimple字符串和一个自定义指令,将'$ data'替换为相应的列/行值.

To solve this, I've used a '$data' as asimple string and a custom directive to replace '$data' with the corresponding column/row value.

在数据表组件中,我在每个tbody td密码上使用appDatatableContent伪指令,row数据和colum设置(该伪指令仅在colum设置具有模板的情况下适用):

In the datatable component I'm using a appDatatableContent directive on each tbody td passig the row data and the colum settings (the directive only applies if the colum settings has a template):

<table class="table">
  <thead>
    <tr>
      <th *ngFor="let col of columns" [ngClass]="getColumnHeaderClasses(col)" (click)="onReorder(col)">{{col.header}}</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let row of items.Items">
      <td *ngFor="let col of columns" appDatatableContent [column]="col" [row]="row">
        <ng-container *ngIf="!col.template; else col.template">
          {{row[col.attribute]}}
        </ng-container>
      </td>
    </tr>
  </tbody>
</table>

该伪指令基本上是在其中查找包含'$ data'的元素,并将'$ sdata'替换为相应的列值,如下所示:

And the directive basically looks for an element that contains '$data' inside and replaces '$sdata' for the corresponding column value as this:

ngAfterViewInit() {
  if (!this.column.template) {
    return;
  }
  const element: HTMLElement = this.element.nativeElement;
  const value = this.row[this.column.attribute];

  const children = element.getElementsByTagName('*');
  const length = children.length;

  for (let i = 0; i < length; i++) {
    const currentNode = children[i];
    if (!currentNode.children || !currentNode.children.length) {
      const originalHTML: string = currentNode.innerHTML;
      const fixedHTML = originalHTML.replace('$data', value);
      currentNode.innerHTML = fixedHTML;
    }
  }
}

此外,请注意,每个单元格都有<ng-container *ngIf="!col.template; else col.template">,因此,如果绑定了任何模板,则单元格内容将呈现该模板,但是问题在于如何将参数(特别是行对象)传递给模板,以便模板可以对该参数使用插值.

Also, notice that each cell has <ng-container *ngIf="!col.template; else col.template"> so if there is any template binded, the cell content will render that template, but the problem is how to pass arguments (specifically the row object) to the template so the template can use interpolation with that parameter.

查看工作中的矮人: https://plnkr.co/edit/84jhiquT5q3OQaCxTa5i

但这似乎不是最好的方法,因为我只是替换一个字符串值,所以无法利用很多角度功能.

But It doesn't seems to be the best approach, because i can not get advantage of a lot o angular power since I'm just replacing a string value.

那么,¿我如何定义一个动态模板,该模板可以使用迭代变量来呈现自定义单元格内容?

So, ¿How can I define a dynamic template that can use a iteration variable to render custom cell contents?

推荐答案

您可以使用内置指令NgTemplateOutlet轻松地解决您的问题,该指令允许您将上下文传递给EmbeddedView(ng-template)

You can easily solve your problem by using built-in directive NgTemplateOutlet which allows you to pass context to EmbeddedView (ng-template)

首先删除DatatableContentDirective

然后在其中更改标记

data-table.component.html

<td *ngFor="let col of columns">
  <ng-container *ngIf="!col.template; else customTemplate">
     {{row[col.attribute]}}
  </ng-container>
  <ng-template #customTemplate 
     [ngTemplateOutlet]="col.template"
     [ngTemplateOutletContext]="{ col: col, row: row }">
  </ng-template>
</td>

并在父组件中使用

<ng-template #titleTemplate let-col="col" let-row="row">
  <a role="button" ...>
       <b>Custom</b> {{row[col.attribute]}}
  </a>
</ng-template>

柱塞示例

Plunker Example

另请参阅有关模板变量let-name

See also more information about template variable let-name

这篇关于角度4:带插值的动态模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆