安全地获取延迟加载的DOM元素的引用



我有一个模板部分,只有当相应的对象存在时,它才会出现在DOM中。此外,我想获取表单引用,并将fromEvent("更改"(Observable附加到它上

由于数据可能在ngAfterViewInit之后到达,因此不会有要获取的引用。

查看

<div *ngIf="user$ | async">
<form id="form" #form></form>
</div>

组件

@ViewChild('form') form;
ngOnInit(){
this.user$ = this.someService.getUser() // returns Observable<User>
}
ngAfterViewInit(){
const form = document.getElementById('form')
fromEvent(form || this.form,'change')...
}

我也试着把它移到可观察的回调,比如

ngAfterViewInit(){
this.user$ = this.someService.getUser().pipe(map(res => {
const form = document.getElementById('form')
fromEvent(form || this.form,'change')...
return res
}))
}

请不要建议任何涉及setTimeout((的解决方案

在代码中使用

@ViewChild('form') form;

它基本上说"在组件中定义一个实例变量form,并将其值设置为#form标识的任何DOM元素

一旦创建了由#form标识的元素,Angular就会设置实例变量form的值。

关键是,在你的ngAfterViewInit中,你说的是

ngAfterViewInit(){
const form = document.getElementById('form')
fromEvent(form || this.form,'change')...
}

它表示您希望使用id为form的元素的值来设置仅在ngAfterViewInit方法中可见的变量form

ngAfterViewInit运行时,该元素可能还不存在,您也不知道它将在何时创建。顺便说一句,您还创建了第二个仅在ngAfterViewInit中可见的变量form,以保存this.form应该保存的内容,即Component实例变量。

您可以考虑的是删除@ViewChild('form') form;代码和ngAfterViewInit逻辑,只需在html元素(如(中添加一个事件formChanged

<div *ngIf="user$ | async">
<form id="form" (changed)="formChanged($event)"></form>
</div>

然后实现一个方法formChaged(event)来做你需要做的任何事情

@Picci的回答是正确的,即对于您发布的代码,您应该简单地在表单标记上使用(更改的(Angular事件,而不是直接挂接到DOM。然而,如果您确实需要像您所说的那样获得对延迟加载组件的引用,则需要执行以下操作:

formInitialised: bool = false;
// Implement AfterViewChecked to run this each time the view
// changes - note this will run many times, so you need to keep
// track of whether you have done whatever form initialisation
// you need.
ngAfterViewChecked() {
// Check if form is now defined
if (this.form && !this.formInitialised) {
// Do whatever you need to do with this.form
this.formInitialised = true;
}
// If the form has disappeared from the page, update
// our flag to say so.
if (!this.form && this.formInitialised) this.formInitialised = false;
}

最新更新