Angular 2+:将组件用作另一个组件中的输入

时间:2018-11-02 05:21:31

标签: angular typescript angular-directive angular-components

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

例如:

我想要综合表格组件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']的字符串数组。它应该包含dataSource行名称或附加列名称。

我知道如何使用ng-content,但情况并非如此。所不同的是,我应该在社交场所使用部分内容。也许我应该使用ng-contet,但是我什么都不知道。

我确定我的目标是可行的,因为Angular材质表的工作方式如下:

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

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

任何有关该主题的信息或文章,我都会致敬!

2 个答案:

答案 0 :(得分: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>

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

<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材料团队为此类模板https://github.com/angular/material2/blob/f2c7205d6608d36a2016d90090be2a78d4f3233e/src/lib/table/cell.ts#L32创建了专用指令,这些指令保留了对嵌入式模板https://github.com/angular/material2/blob/676ce3b285718d2ee19ad6ae5702917566167641/src/cdk/table/cell.ts#L34的引用

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

<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),但可以在此处找到简单的实现:

答案 1 :(得分:2)

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

如果内容DOM更改,并且有一个新的子项与选择器匹配,则该属性将被更新。

您的孩子component.html读为

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

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

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

将内容从父级传递到子级的方法

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

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

在子组件中,您可以添加尽可能多的模板,在这些模板中,所有模板将与从父组件传递来的内容一起放置-这是将内容从父项传递给子组件的另一种方式-希望这会有所帮助-谢谢Happy编码! !

点击here供参考