如何区分通过ContentChildren传递给组件的多个模板?

时间:2018-04-06 14:13:26

标签: angular

例如,假设我想实现一个数据表组件,我可以为每个列的单元格传递一个可选模板:

@Component({
  selector: 'datatable',
  template: `
<table>
  <tbody>
    <tr *ngFor="let row of rows">
      <td *ngFor="let col of columns">
        <ng-container *ngIf="getTemplate(col)">
          <ng-container *ngTemplateOutlet="getTemplate(col)"
                        ngTemplateOutletContext="{$implicit: row}">
          </ng-container>
        </ng-container>
        <ng-container *ngIf="!col.cellTemplate">
            {{row[col.prop]}}
        </ng-container>
      </td>
    </tr>
  </tbody>
</table>`,
})
export class DatatableComponent implements OnInit {
  @ContentChildren('cellTemplate') cellTemplates: QueryList<TemplateRef<any>>;
  ...
}

我想这样使用:

<datatable [columns]='columns'
           [rows]='rowCollection'>
  <ng-template #cellTemplate let-row prop="id">
    <a href='some url'> {{row.id}} </a>
  </ng-template>

  <ng-template #cellTemplate let-row prop="name">
    <a href='some other url'> {{row.name}} </a>
  </ng-template>
</datatable>

我遇到的问题是:如何实现getTemplate函数,它应该在每个列的cellTemplates中找到正确的模板?例如,我为每个模板指定了一个属性prop,但我不知道如何从TemplateRef中访问此值。

1 个答案:

答案 0 :(得分:1)

经过一番努力,我想出了这个。解决方案是:

  1. 创建一个指令,该指令将同时包含模板的标识符和模板本身。
  2. 将TemplateRef注入指令的构造函数;当指令放在ng-template元素上时,会注入相应的模板。
  3. 将每个模板的模板引用变量设置为指令
  4. 代码:

    @Directive({selector: '[propName]', 'exportAs': 'propName'})
    export class PropName  { 
      constructor (public tmpl: TemplateRef<any>) { }
      @Input('propName') propName: string;    
    }
    
    ...
    
    <datatable [columns]='columns'
               [rows]='rowCollection'>
      <ng-template #cellTemplate="propName" propName="id">
        <a href='some url'> {{row.id}} </a>
      </ng-template>
    
      <ng-template #cellTemplate="propName" propName="name">
        <a href='some other url'> {{row.name}} </a>
      </ng-template>
    </datatable>
    

    ContentChildren列表的每个元素(定义为@ContentChildren('cellTemplate') cellTemplates)将具有propName属性(标识模板)和tmpl属性(TemplateRef)。