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

Angular 2+: Use component as input in another component

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

例如:

我想要构建 table 组件 AppTableComponent:

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

dataSource 是类似于 Model[]Person[]Car[] 的数据数组总和。 columns 是一个类似于 ['id', 'isActive', 'name', 'actions'] 的字符串数组。它应该包含数据源行属性名称或附加列名称。

我知道如何使用 ng-content 但这不是相同的情况。不同之处在于我应该在连续的地方使用部分内容。也许我应该使用ng-contet,但我不知道。

我确定我的目标是可行的,因为 Angular material table 是这样工作的:

<mat-table #table [dataSource]="dataSource">
    <ng-container matColumnDef="position"></ng-container>
    <ng-container matColumnDef="weight"></ng-container>
</mat-table>

请不要建议我使用 Angular material table 组件。我不需要 table。我只是想学点新东西。

如果有任何关于该主题的信息或文章,我将不胜感激!

如果您想在消费者部分管理模板,则必须使用 Angular 嵌入式视图 (ng-template)。这就是 material 在其 table 实施中使用的内容。

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

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

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

这里可以看到<ng-template matHeaderCellDef>,可以用ContentChild.

得到

Angular material 团队为此类模板创建专用指令 https://github.com/angular/material2/blob/f2c7205d6608d36a2016d90090be2a78d4f3233e/src/lib/table/cell.ts#L32 which keep references to embedded templates https://github.com/angular/material2/blob/676ce3b285718d2ee19ad6ae5702917566167641/src/cdk/table/cell.ts#L34

Material table 组件的模板如下:

<ng-container headerRowOutlet></ng-container>
<ng-container rowOutlet></ng-container>
<ng-container footerRowOutlet></ng-container>

还有指令助手,如:

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

以便我们可以使用低级别 api 创建基于嵌入式模板的元素,例如 ViewContainerRef.createEmbeddedView(templateRef) 但可以在此处找到简单的实现:

您可以使用@ContentChild('tableHeader') header: TemplateRef<any>; 您可以使用ContentChild从内容DOM中获取第一个元素或匹配选择器的指令。

如果内容 DOM 发生变化,并且新的 child 匹配选择器,属性 将被更新。

您的 child component.html 读作

 <ng-template [ngTemplateOutlet]="header"></ng-template>
 <ng-template [ngTemplateOutlet]="body"></ng-template>

其中 [ngTemplateOutlet] 将读取 属性 值并将内容粘贴到指定模板中

最后,当您引用 parent 组件中的内容时,它将与上述模板一起放置

将内容从parent传递到child的方法

<compoent-selector>
     <ng-template #tableHeader></ng-template>
     <ng-template #body></ng-template>
</component-selector>

<ng-template> 中的任何内容都将放置在 child 组件中

在 child 组件中,您可以添加尽可能多的模板,所有模板都将与从 parent 组件传递的内容一起放置 - 这是从 [=] 传递内容的另一种方式44=] 到 child - 希望这会有所帮助 - 谢谢编码愉快!

点击here参考