How to check whether ngIf has taken effect

前端 未结 2 1682
深忆病人
深忆病人 2020-12-06 04:27

What I\'m Doing
I have a component that hides/shows using *ngIf based on a simple Boolean. When the component becomes visible I want to app

相关标签:
2条回答
  • 2020-12-06 05:24

    This question is fairly old, and the current solution may not have been available at that time.

    The setTimeout() method is perfectly viable, but has a significant downside. If you just set a class to position an element, like I did, you get a jumpy result, since the code is executed after the angular loop.

    Using ChangeDetectorRef produces a result that does not jump.

    So instead of this:

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

    You could do this:

    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');
         // ...
      }
    }
    
    0 讨论(0)
  • 2020-12-06 05:27

    If you flip the boolean value to true and in the next line of code you try to get a reference to the component or DOM element controlled by NgIf... well, that component or DOM element doesn't exist yet. Angular doesn't run in parallel with your code. Your JavaScript callback has to finish, then Angular (change detection) runs, which will notice the boolean value change and create the component or DOM element and insert it into the DOM.

    To fix your issue, call setTimeout(callbackFn, 0) after you flip the boolean value. This adds your callbackFn to the JavaScript message queue. This will ensure that Angular (change detection) runs before your callback function. Hence, when your callbackFn executes, the element you want to focus should now exist. Using setTimeout(..., 0) ensures that your callbackFn gets called in the next turn of the JavaScript event loop.

    This technique of using setTimeout(..., 0) is used in the LifeCycle hooks dev guide when discussing the AfterView* hooks.

    Here are a few other examples, if you need more details:

    • https://stackoverflow.com/a/35752722/215945 - uses focus()
    • https://stackoverflow.com/a/34757864/215945 - uses Renderer to call focus
    • https://stackoverflow.com/a/36338181/215945 - uses a directive to set the focus
    • https://stackoverflow.com/a/34503163/215945 - shows 4 different ways to do it
    0 讨论(0)
提交回复
热议问题