简体   繁体   English

角度4:带插值的动态模板

[英]Angular 4: Dynamic template with interpolation

I'm building a data table component that is being designed as very generic component. 我正在构建一个数据表组件,它被设计为非常通用的组件。

The idea is to define the table as this: 我们的想法是将表定义为:

<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>

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. 在内部,表将按列和另一个ngFor按项执行ngFor。

This part was simple and now it's working very well, the thing becomes tricky when I want custom html content into the td; 这部分很简单,现在它运行得很好,当我想要自定义html内容到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>

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作为迭代变量,但它实际上不起作用,我只是说明了我想要做的事情。

To solve this, I've used a '$data' as asimple string and a custom directive to replace '$data' with the corresponding column/row value. 为了解决这个问题,我使用'$ data'作为简单字符串和自定义指令将'$ data'替换为相应的列/行值。

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): DataTable中的分量我使用的是appDatatableContent每个指令tbody td passig的row数据和colum设置(指令只适用,如果科拉姆设置有一个模板):

<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>

And the directive basically looks for an element that contains '$data' inside and replaces '$sdata' for the corresponding column value as this: 该指令基本上查找内部包含'$ data'的元素,并替换相应列值的'$ sdata',如下所示:

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;
    }
  }
}

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

See working plunker: https://plnkr.co/edit/84jhiquT5q3OQaCxTa5i 见工作人员: 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? 那么,¿如何定义一个可以使用迭代变量来呈现自定义单元格内容的动态模板?

You can easily solve your problem by using built-in directive NgTemplateOutlet which allows you to pass context to EmbeddedView ( ng-template ) 您可以使用内置指令NgTemplateOutlet轻松解决您的问题,该指令允许您将上下文传递给EmbeddedViewng-template

First remove DatatableContentDirective 首先删除DatatableContentDirective

Then change markup in 然后更改标记

data-table.component.html 数据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>

and use in parent component 并在父组件中使用

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

Plunker Example Plunker示例

See also more information about template variable let-name 另请参阅有关模板变量let-name更多信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM