4

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!

powerseed
  • 1,090
  • 3
  • 17
  • 29
  • 2
    You should run this piece of code after whenever you calculate `booleanVariable`, instead of wanting to change the behaviour of a lifecycle hook. Also, use [ViewChild](https://angular.io/api/core/ViewChild) instead of accessing the DOM directly in angular. – Ricky Mo Dec 20 '21 at 06:11
  • Possible duplicate of https://stackoverflow.com/questions/36101756/angular2-routing-with-hashtag-to-page-anchor – Dev Gourav Dec 20 '21 at 06:13

3 Answers3

0

Try using _elementRef instead:

this._elementRef.nativeElement.querySelector('#'+fragment)
Spankied
  • 1,626
  • 13
  • 21
0

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.

Emmanuel
  • 4,933
  • 5
  • 46
  • 71
0

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.

powerseed
  • 1,090
  • 3
  • 17
  • 29