4

我正在构建一个数据表组件,它被设计为非常通用的组件。角度4:带插值的动态模板

的思想是定义表作为这样的:

<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部件,以及通过定义数据表柱我们可以决定女巫属性应该显示表。在内部,表格将按列和另一个ngFor按项目执行ngFor。

这部分很简单,现在它工作得很好,当我想要自定义HTML内容到td时,事情变得棘手;事情是这样的:

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

为了解决这个问题,我使用'$ data'作为简单的字符串和自定义指令来将'$ data'替换为相应的列/行值。

在我使用的是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> 

而且该指令基本上看起来为包含“$数据”内,并替换“$ 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; 
    } 
    } 
} 

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

见工作plunker:https://plnkr.co/edit/84jhiquT5q3OQaCxTa5i

不过,这并不似乎是最好的方法,因为我无法获得的优势,大量邻角功率的,因为我只是替换字符串值。

因此,我如何定义一个可以使用迭代变量呈现自定义单元格内容的动态模板?

回答

8

您可以轻松地通过使用内置指令NgTemplateOutlet,它允许你通过上下文EmbeddedViewng-template

解决您的问题

首先拆下DatatableContentDirective

然后在

数据 - 更改标记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

+0

这就是我正在寻找的!!!!! :D 非常感谢。 –

+0

不客气!很高兴听到它帮助:) – yurzui

+0

非常明确的答案 –