我有一个模板部分,仅当对应的对象存在时才在DOM中。此外,我想获取表单引用,并向其附加一个fromEvent('change')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()的解决方案
答案 0 :(得分:2)
在您的代码中使用
@ViewChild('form') form;
基本上说“在Component中定义实例变量form
,并将其值设置为#form
所标识的任何DOM元素。
一旦创建了#form
所标识的元素,Angular就会设置实例变量form
的值。
重点是您在ngAfterViewInit
中说
ngAfterViewInit(){
const form = document.getElementById('form')
fromEvent(form || this.form,'change')...
}
这表示您要设置一个变量form
,该变量仅在ngAfterViewInit
方法中可见,且其元素的值为form
。
当ngAfterViewInit
运行时,该元素可能还不存在,并且您真的不知道何时创建。顺便说一句,您还创建了第二个变量form
,该变量仅在ngAfterViewInit
中可见,以容纳应由this.form
持有的同一事物,即Component实例变量。
您可以考虑删除@ViewChild('form') form;
代码和ngAfterViewInit
逻辑,然后将事件formChanged
添加到html元素(例如
<div *ngIf="user$ | async">
<form id="form" (changed)="formChanged($event)"></form>
</div>
然后实现方法formChaged(event)
来完成您需要做的所有事情。
答案 1 :(得分:0)
@Picci的回答正确地表明,对于您发布的代码,您应该仅在form标记上使用(已更改的)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;
}