问题
所以我有两个 Angular 组件,一个父组件和一个子组件。父组件将自定义模板传递给子组件,然后子组件使用 ngTemplateOutlet 将模板与自己的数据结合起来。
这在大多数情况下效果很好。不幸的是,我在尝试从子级访问此父模板的 DOM 元素时遇到了问题。
如果我尝试使用<div #container></div>
从默认子模板访问@ViewChild('container',{static: false})
,它会毫无问题地获取元素。当我使用 app.component 传入的自定义模板执行相同操作时,我收到错误“无法读取未定义的属性‘nativeElement’”。
我还需要做什么才能访问我的模板的 DOM?
这是一个Stackblitz
App.Component(父)
import { Component } from "@angular/core";
@Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {}
<child [customTemplate]="parentTemplate"></child>
<ng-template #parentTemplate let-context="context">
<div #container>HELLO FROM CONTAINER</div>
<button (click)="context.toggleShow()">Toggle Display</button>
<div *ngIf="context.canShow">Container contains the text: {{context.getContainerText()}}</div>
</ng-template>
child.component(儿童)
import {
Component,
ElementRef,
Input,
TemplateRef,
ViewChild
} from "@angular/core";
@Component({
selector: "child",
templateUrl: "./child.component.html",
styleUrls: ["./child.component.css"]
})
export class ChildComponent {
@Input() public customTemplate!: TemplateRef<HTMLElement>;
@ViewChild("container", { static: false })
public readonly containerRef!: ElementRef;
templateContext = { context: this };
canShow: boolean = false;
toggleShow() {
this.canShow = !this.canShow;
}
getContainerText() {
return this.containerRef.nativeElement.textContent;
}
}
<ng-container *ngTemplateOutlet="customTemplate || defaultTemplate; context: templateContext">
</ng-container>
<ng-template #defaultTemplate>
<div #container>GOODBYE FROM CONTAINER</div>
<button (click)="toggleShow()">Toggle Display</button>
<div *ngIf="canShow">Container contains the text: {{getContainerText()}}</div>
</ng-template>
我的问题
如何使用@ViewChild 从随 DOM 中的任何更改而更新的外部模板访问此 div?(注意:删除 *ngIf 不是此项目的选项)
这是什么原因造成的?我可以使用任何生命周期方法来解决此问题吗?
我的预感 我猜在使用新模板更新 DOM 之前调用 ViewChild,我需要为 DOM 更改设置一个侦听器。我试过这个但失败了,所以我真的很感激一些关于如何最好地进行的智慧。提前致谢 :)
<div #container></div>
编辑:无论您是传入自定义模板还是使用默认模板,此解决方案都需要正确显示。