Marko Taht
Marko Taht

Reputation: 1522

Angular2 do actions after dom has finished rendering

I have a large ngx-bootstrap accordion on the page. When i open some of the lower accordions i want it to scroll the page so that the opened accorion starts at the top of the window. I achieved the scrolling part with scrollIntoView, but now the issue is to execute it at the right time. im currently doing it in the ngAfterViewChecked, but the viewChecked is fired multiple times (mousemove, mouseenter, etc...). Is there a way to fire a piece of code only after the DOM has finished rendering separately from the angular2+ changeDetection?

SOLUTION

This is the solution that started working.

constructor(elementRef: ElementRef) {
    this.elementRef = elementRef
  }

getData(){
   this.getService().then(result => {
      #do stuff with result
      setTimeout(() => this.scrollToBegin());
    }).catch((err: any) => {
    });
}

scrollToBegin(): any{
      this.elementRef.nativeElement.scrollIntoView();
    }

Upvotes: 3

Views: 4257

Answers (3)

Vahid
Vahid

Reputation: 7551

AFAIK you just have ngAfterViewChecked and ngAfterViewInit for detecting dom updates.

In my experience, sometimes you need to write the code for dom changes inside a settimeout to schedule a macrotask (asynchronous update) for that so that your code will run in the next cycle of change detection (which is exactly what you need). For more details see this article

Place your could inside a settimeout in the end of your block code (and remove it from ngAfterViewChecked). Some examples:

setTimeout(() => htmlInputElement.focus()); // focus an input
setTimeout(() => htmlElement.scrollIntoView()); // scroll into view

Upvotes: 3

piotr szybicki
piotr szybicki

Reputation: 1602

This is a dumb response. but have you consider using the custom event isOpenChange shipped with accordeon:

      <accordion-group heading="Group with isOpenChange event listener" 
(isOpenChange)="log($event)">
        <p>Some content</p>
      </accordion-group>

and then in copponent:

log(event: boolean) {
    console.log(`Accordion has been ${event ? 'opened' : 'closed'}`);
  }

Upvotes: 0

Ashish Yadav
Ashish Yadav

Reputation: 2008

Check Angular documentation for different lifecycle hook. Lifecycle hooks are called after the the component view is initialized.

AfterViewInit() will executes once as per your requirement.

A callback method that is invoked immediately after Angular has completed initialization of a component's view. It is invoked only once when the view is instantiated.

ngAfterVIewChecked() is called after the component's view is loaded but it detects the changes and execute.

Upvotes: 0

Related Questions