Angular: 在 ng-template 中访问 elementRef

Angular: Access elementRef inside an ng-template

我通过 ng-template 获得了一个呈现不同表单字段组件的组件。现在我想访问最后呈现的组件中的一个函数。

我尝试使用带有字符串 select 的 ViewChildren() 注释访问它,或者所有字段组件(文本字段,select 字段)扩展自。

allFields 始终为空。还尝试以 ContentChildrenAfterContentInit 生命周期挂钩访问它。任何想法如何实现这一目标?

这很像 this 问题,但仍未得到解答,所以我想我会再问一遍。谢谢

HTML

<div *ngFor="let field of fields; fieldIndex as index">
  <ng-container *ngTemplateOutlet="getTemplate()"></ng-container>
</div>
<input type="button" (click)="doFunctionOnLastField()">

<ng-template #text>
 <text-field #field [field]=this.fields[fieldIndex]></text-field>
<ng-template>

<ng-template #select>
 <select-field #field [field]=this.fields[fieldIndex]></text-field>
<ng-template>

TypeScript

export class FormComponent implements OnInit, AfterViewInit {

 @Input() fields: FieldBase[];
 @ViewChild('text') text: TemplateRef<any>
 @ViewChild('select') select: TemplateRef<any>
 @ViewChildren('field') allFields;

 lastField: FieldBaseComponent;
 fieldIndex: number = 0;

 ngOnInit(): void {
  //...
 }

 ngAfterViewInit(): void {
  this.lastField = this.allFields.last; //this.allFields is empty
 }

 getTemplate() {
  // returns my template
 }

 doFunctionOnLastField() {
  this.lastField.someFunctionInsideTheField(); //this.lastField... is undefined
 }
}

呈现的视图及其子视图仅在模板在 ViewContainerRef 中呈现时才可访问,因此 right here.

使用ngTemplateOutlet时无法获得渲染视图,所以我认为最好的办法是复制代码并修改它以满足您的要求。

getTemplate() 方法将在调用 ngAfterViewInit() 之前被调用。

getTemplate() 第一次被调用时,它甚至不会 return TemplateRef,只有在下一个变化检测周期中,TemplateRef 才会正确 return ed 并且您的字段将被渲染。您甚至可能会遇到 ExpressionChangedAfterItHasBeenCheckedError 错误。

因此,当 ngAfterViewInit 被调用时,您的字段不会被渲染,因此 this.allFields.last 将是未定义的。

尝试为 textselect ViewChild 声明将 static 元数据 属性 指定为 true

@ViewChild('text', { static: true }) text: TemplateRef<any>;
@ViewChild('select', { static: true }) select: TemplateRef<any>;