Angular 2+:使用组件作为另一个组件的输入

Lak*_*mon 5 typescript angular-directive angular-components angular

如何使用组件作为 Angular 中另一个组件的输入数据?

\n\n

例如:

\n\n

我想要构建表格组件AppTableComponent:

\n\n
<app-table [dataSource]="dataSource" [columns]="columns">\n  <ng-container tableColumnDef="actions">\n    <a routerLink="/model/edit/{{item.id}}" routerLinkActive="active">Edit</a>\n    <a routerLink="/model/delete/{{item.id}}" routerLinkActive="active">Delete</a>\n  </ng-container>\n  <ng-container tableColumnDef="isActive">\n    <div [ngClass]="{cercl:true, \'is-active\':item.is_active}">&nbsp;</div>\n  </ng-container>\n</app-table>\n
Run Code Online (Sandbox Code Playgroud)\n\n

dataSource是数据数组之和,如Model[]orPerson[]Car[]columns是一个字符串数组,如[\'id\', \'isActive\', \'name\', \'actions\']. 它应该包含数据源行属性名称或附加列名称。

\n\n

我知道如何使用ng-content,但它不是相同的情况。不同之处在于我应该在多个地方使用部分内容。也许我应该使用 ng-contet,但我不知道\xe2\x80\x99t 是什么。

\n\n

我确信我的目标是可能的,因为 Angular 材质表的工作原理如下:

\n\n
<mat-table #table [dataSource]="dataSource">\n    <ng-container matColumnDef="position"></ng-container>\n    <ng-container matColumnDef="weight"></ng-container>\n</mat-table>\n
Run Code Online (Sandbox Code Playgroud)\n\n

请不要建议我使用 Angular 材料表组件。我不需要桌子。我只是想学点新东西。

\n\n

我将非常感谢有关该主题的任何信息或文章!

\n

yur*_*zui 4

如果你想在消费者部分管理模板,那么你必须使用 Angular 嵌入视图(ng-template)。这就是材料在其表实现中使用的内容。

<table mat-table [dataSource]="dataSource">
  <ng-container matColumnDef="position">
    <th mat-header-cell *matHeaderCellDef> No. </th>
    <td mat-cell *matCellDef="let element"> {{element.position}} </td>
  </ng-container>
Run Code Online (Sandbox Code Playgroud)

您可以说没有任何嵌入视图,但让我们看看上面模板的扩展版本:

<table mat-table [dataSource]="dataSource">
  <ng-container matColumnDef="position">
    <ng-template matHeaderCellDef>
      <th mat-header-cell> No. </th>
    </ng-template>
    <ng-template matCellDef let-element="$implicit">
      <td mat-cell> {{element.position}} </td>
    </ng-template>
  </ng-container>
Run Code Online (Sandbox Code Playgroud)

我们可以注意到<ng-template matHeaderCellDef>这里可以通过使用 来获得ContentChild

Angular Material 团队为此类模板创建专用指令https://github.com/angular/material2/blob/f2c7205d6608d36a2016d90090be2a78d4f3233e/src/lib/table/cell.ts#L32保留对嵌入式模板的引用https://github.com/角度/material2/blob/676ce3b285718d2ee19ad6ae5702917566167641/src/cdk/table/cell.ts#L34

材料表组件具有如下模板:

<ng-container headerRowOutlet></ng-container>
<ng-container rowOutlet></ng-container>
<ng-container footerRowOutlet></ng-container>
Run Code Online (Sandbox Code Playgroud)

还有一些指令帮助器,例如:

@Directive({selector: '[headerRowOutlet]'})
export class HeaderRowOutlet implements RowOutlet {
  constructor(public viewContainer: ViewContainerRef,
              public elementRef: ElementRef) { }
}
Run Code Online (Sandbox Code Playgroud)

这样我们就可以使用低级 api 来创建基于嵌入模板的元素,例如,ViewContainerRef.createEmbeddedView(templateRef)但简单的实现可以在这里找到: