How to make sure ngAfterViewInit runs after a certain HTML element is rendered?

Viewed 225

In HTML, there is a <a> that redirects to another component, and after that scrolls to a certain anchor.

In the target component, I have the following code

  ngAfterViewInit(): void {
    this.route.fragment.subscribe(fragment => {
      const elmntLoc: HTMLElement = document.getElementById(fragment);
      window.scroll({
        top: elmntLoc.offsetTop,
        behavior: "smooth"
      });
    });
  }

However, I found that document.getElementById(fragment); is always null, because this element is displayed conditionally using ngIf = booleanVariable, and when this ngAfterViewInit life cycle hook runs, this booleanVariable is not calculated yet.

I am wondering how to make sure ngAfterViewInit runs after booleanVariable is calculated and therefore this element is rendered?

I tried to use setTime but it seems hacky...

Thanks in advance!

3 Answers

Try using _elementRef instead:

this._elementRef.nativeElement.querySelector('#'+fragment)

You could try waiting for the next animation frame to give a chance for the html element to render.

ngAfterViewInit(): void {
  this.route.fragment.subscribe(fragment => {
    window.requestAnimationFrame(_ => {
      const elmntLoc: HTMLElement = document.getElementById(fragment);
      window.scroll({
        top: elmntLoc.offsetTop,
        behavior: "smooth"
      });
    }
  });
}

Need to see more of your code to give a more robust answer.

Thanks for the answers but they don't work properly I am afraid... (Perhaps I tried them in a wrong way.)

I managed to solve this problem using

  @ViewChild('elementId') set elementName(elementName: ElementRef) {
      # code to scroll to a certain section of the page.
  };

The method will run after this ViewChild is rendered.

Related