如何检查ngIf是否生效

时间:2016-05-20 21:00:23

标签: angular

我在做什么
我有一个基于简单布尔值使用concat隐藏/显示的组件。当组件变得可见时,我想将焦点应用于其模板中的子元素。

问题
如果我翻转布尔值,组件会正确显示,但如果我尝试使用#photos li { width: 30%; float: left; display: block; margin: 1px; } #photos img { max-width: 100% } 获取对子元素的引用,则只返回*ngIf。如果我等待几秒钟,相同的代码将返回对我所期望的元素的引用。

投机
我假设在翻转后,布尔角度经过整个渲染周期以显示新的可见组件,并且在我在下一行中应用this._elRef.nativeElement.querySelector("div#test")时尚未完成。

我想知道
所以我想知道的是,我怎样才能确定我的null已经生效并且元素是他们在DOM中的选择?是否存在回调等问题querySelector()或者我可以强制视图更新并从中获取回调吗?

我希望这是有道理的。这是一个漫长的一天(漫长的一周),我非常累。
谢谢所有

如果有帮助,我使用的是Angular2 v2.0.0-beta.15

2 个答案:

答案 0 :(得分:24)

如果将布尔值翻转为true并在下一行代码中尝试获取对由NgIf控制的组件或DOM元素的引用...那么,该组件或DOM元素不会#39但是还存在。 Angular并不与您的代码并行运行。您的JavaScript回调必须完成,然后运行Angular(更改检测),这将注意到布尔值的更改并创建组件或DOM元素并将其插入DOM。

要解决您的问题,请在翻转布尔值后调用setTimeout(callbackFn, 0)。这会将callbackFn添加到JavaScript message queue。这将确保Angular(更改检测)在回调函数之前运行。因此,当您callbackFn执行时,您想要关注的元素现在应该存在。使用setTimeout(..., 0)可确保在JavaScript event loop的下一回合调用callbackFn

在讨论AfterView* hooks时,LifeCycle钩子开发指南中使用了setTimeout(..., 0)这种使用技巧。

如果您需要更多详细信息,请参阅以下几个示例:

答案 1 :(得分:8)

这个问题相当陈旧,当时可能还没有当前的解决方案。

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');
     // ...
  }
}