我在做什么
我有一个组件,它根据一个简单的布尔值使用*ngIf隐藏/显示。当组件可见时,我希望将焦点应用到其模板中的子元素。
问题
如果我正确地翻转该组件显示的布尔值,但是如果我尝试使用this._elRef.nativeElement.querySelector("div#test")获得对子元素的引用,则只会返回null。如果我等待几秒钟,相同的代码将像我预期的那样返回对元素的引用。
炒作
我假设在翻转布尔角之后,经过一个完整的呈现周期来显示新可见的组件,并且在我将querySelector()应用到下一行时,这个过程还没有完成。
我想知道的
因此,我想知道的是,如何确定我的ngIf已经生效,并且元素在DOM中被选中了?
是否存在用于ngIf的回调,或者我可以强制视图更新并从中获取回调吗?
我希望这是合理的。这是一个漫长的一天(漫长的一周),我是超级累。
谢谢大家
如果有用的话,我使用的是Angular2 v2.0.0-beta.15
发布于 2016-05-20 21:17:44
如果将布尔值翻转到true,并在下一行代码中尝试获取对由NgIf控制的组件或DOM元素的引用.这个组件或DOM元素还不存在。角形不会与代码并行运行。您的JavaScript回调必须完成,然后运行角(变化检测),它将注意到布尔值的变化,并创建组件或DOM元素并将其插入DOM中。
若要解决问题,请在翻转布尔值后调用setTimeout(callbackFn, 0)。这会将callbackFn添加到JavaScript消息队列中。这将确保角(变化检测)在回调函数之前运行。因此,当您的callbackFn执行时,您想要聚焦的元素现在应该存在。使用setTimeout(..., 0)可以确保您的callbackFn在JavaScript事件循环的下一个回合中被调用。
在讨论setTimeout(..., 0)时,LifeCycle钩子开发指南中使用了这种使用钩子的技术。
如果您需要更多的详细信息,下面是一些其他示例:
focus发布于 2017-06-09 14:12:32
这个问题相当老,当时可能还没有解决办法。
setTimeout()方法是完全可行的,但是有一个明显的缺点。如果您只是设置一个类来定位一个元素,就像我所做的那样,您会得到一个不稳定的结果,因为代码是在角循环之后执行的。
使用ChangeDetectorRef会产生一个不会跳转的结果。
所以,不是这样的:
class Foo {
public isDisplayed = false;
constructor(@Inject(ElementRef) private elementRef: ElementRef) {
}
public someMethod(): void {
this.isDisplayed = true;
setTimeout(() => {
const child = this.elementRef.nativeElement.querySelector('.child-element');
// ...
});
}
}你可以这样做:
class Foo {
public isDisplayed = false;
constructor(@Inject(ElementRef) private elementRef: ElementRef,
@Inject(ChangeDetectorRef) private changeDetectorRef: ChangeDetectorRef) {
}
public someMethod(): void {
this.isDisplayed = true;
this.changeDetectorRef.detectChanges();
const child = this.elementRef.nativeElement.querySelector('.child-element');
// ...
}
}https://stackoverflow.com/questions/37355768
复制相似问题