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

查看:27
本文介绍了Angular 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我们可以决定witch属性应该显示表格.在内部,该表将按列执行 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' 作为简单的字符串和一个自定义指令来用相应的列/行值替换 '$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 passig row 数据和 colum<上使用了 appDatatableContent 指令/code> 设置(该指令仅适用于列设置具有模板的情况):

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

另外,请注意每个单元格都有 所以如果绑定了任何模板,单元格内容将渲染该模板,但问题是如何将参数(特别是行对象)传递给模板,以便模板可以使用该参数的插值.

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.

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

See working plunker: 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 示例

另见关于模板变量let-name

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

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