如何在 Angular 8/9/10/11 中访问可重用组件中的子模板

How to access child template in reusable component in Angular 8/9/10/11

我创建了通用组件,它将以 table 格式呈现数据。

data-table.component.ts(这是可重用的组件,可以被任何子组件使用)

    @Component({
      selector: 'data-table',
      templateUrl: './data-table.component.html',
      styleUrls: ['./data-table.component.css']
    })
    export class DataTableComponent implements OnInit {
    constructor() { }
    
      ngOnInit(): void {
         //wanted to access child here(or inside any method in this class) to set the width of each <td> from child
      //wanted to access #rowTemplate children from child for all 3 <td> 
      }
setColumnWidth(width: string = "") {
    if (width != "") {
      return 'width:' + width;
    }
  }
    }

数据-table.component.html

<table style="width:100%;">
      <thead>
        <tr>
          <th *ngFor="let c of columns" style="{{setColumnWidth(c.width)}}">
            {{c.fieldTitle}}
          </th>
        </tr>
      </thead>
       <tbody>
        <ng-container *ngTemplateOutlet="rowTemplate"></ng-container>
      </tbody>
    </table>

resource-updates.component.ts(这是子组件)

    @Component({
      selector: 'resource-updates',
      templateUrl: './resource-updates.component.html',
      styleUrls: ['./resource-updates.component.css']
    })
    export class ResourceUpdatesComponent implements OnInit {
      columns: Column[] = [];
      rows: any[] = [];
     
      constructor() { }
    
      ngOnInit(): void {
        //Preparing list for columns
        this.columns.push(new Column({ fieldName: 'Id', fieldTitle: 'Id', isSortable: false, width: '5%' }));
        this.columns.push(new Column({ fieldName: 'Title', fieldTitle: 'Title', width: '60%' }));
        this.columns.push(new Column({ fieldName: 'Type', fieldTitle: 'Type', width: '35%' }));
      
       //Preparing list for rows
       this.rows = [
{"id":5,"title":"Air Gas Guideline","type":"PPT"},
{"id":6,"title":"Air Pollution User Reference","type":"Website"},
{"id":18,"title":"Avian Influenza (H7N9) User Reference","type":"Website"},
{"id":12,"title":"Avian Influenza (H7N9) for high risk","type":"PPT"},
{"id":11,"title":"Avian Influenza (H7N9) for normal","type":"PPT"}
];
      }
    }

resource-updates.component.html(想在columns.width 属性的Parent(公共组件)中设置下面的宽度为3)

  <ng-template #rowTemplate>
    <tr *ngFor="let r of rows">
      <td>{{r.id}}</td>
      <td>{{r.title}}</td>
      <td>{{r.type}}</td>
    </tr>
  </ng-template>
  <data-table [columns]="columns" [rowTemplate]="rowTemplate"></data-table>

任何人都可以帮助访问#rowTemplate 子元素以从列[0].width 和分别设置宽度...

如果我没理解错的话,你想从父组件访问子组件的ng-template?如果是的话,就是我之前create data-table controls.

时使用的情况
  1. 您可以创建一个包含 TemplateRef 的指令 class:
import { Directive, ContentChild, TemplateRef, Input } from "@angular/core";
@Directive({ selector: "np-column" })
export class NpColumnDirective {
      @Input() name: string;
      @ContentChild(TemplateRef) cellTemplate: TemplateRef<any>;
      constructor() { }
}
  1. 然后在您的父组件中使用以下方式访问它:

@ContentChildren(NpColumnDirective) columnComponents: QueryList<NpColumnDirective>;

这是我创建数据的全部代码-table,仅供参考: datatable demo

您需要定义 @ContentChild 并向 DataTableComponent 中的列变量添加 @Input() 注释(包括 Column 接口不在你的问题中):

export interface Column {
  fieldName: string;
  fieldTitle: string;
  isSortable?: boolean;
  width?: string;
}

@Component({
  selector: 'app-data-table',
  templateUrl: './data-table.component.html',
  styleUrls: ['./data-table.component.css']
})
export class DataTableComponent implements OnInit {

  @Input() columns: Column[] = [];

  @ContentChild('rowTemplate') rowTemplate: TemplateRef<any>;

  constructor() { }

  ngOnInit(): void {
  }
}

DataTableComponent 的模板应如下所示:

<table style="width:100%;">
  <thead>
    <tr>
      <th *ngFor="let c of columns" [ngStyle]="{ width: c.width }">
        {{c.fieldTitle}}
      </th>
    </tr>
  </thead>
  <tbody>
    <ng-container *ngTemplateOutlet="rowTemplate"></ng-container>
  </tbody>
</table>

最后 ResourceUpdatesComponent 模板:

<app-data-table [columns]="columns">
  <ng-template #rowTemplate>
    <tr *ngFor="let r of rows">
      <td>{{r.id}}</td>
      <td>{{r.title}}</td>
      <td>{{r.type}}</td>
    </tr>
  </ng-template>
</app-data-table>

Uploaded the working Angular project code to Github

有一篇很好的文章解释了 @ContentChild 的工作原理:Understanding ViewChildren, ContentChildren, and QueryList in Angular


请注意删除了 setColumnWidth() 函数并使用了 ngStyle,“每次 Angular 变化检测时都会调用它运行”,参见 Why you should never use function calls in Angular template expressions