Enn
Enn

Reputation: 2209

How to wait until Angular 2 updates template and run script?

I have a method that I need to execute after DOM has been updated with a data. When I run my method immediately after setting the property (bound to a template), the script does receive empty div in DOM because Angular 2 probably hasn't updated it yet.

Strangely, invoking timeout fixes this issue, but it feels bad. How could I make sure that my method is executed after Angular 2 updates template?

My component:

import { Component, Input, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import { Location } from '@angular/common';
import 'rxjs/add/operator/switchMap';

import { CodeExample } from './code-example.class';
import { CodeExampleService } from './code-example.service';

@Component({
  selector: 'code-example-detail',
  templateUrl: 'code-example-detail.component.html',
})
export class CodeExampleDetailComponent implements OnInit {
  @Input()
  codeExample: CodeExample;

  constructor(
    private codeExampleService: CodeExampleService,
    private route: ActivatedRoute,
    private location: Location,
  ) {
   }

  ngOnInit(): void {
  this.route.params
      .switchMap((params: Params) => this.codeExampleService.getCodeExample(+params['id']))
      .subscribe((codeExample: CodeExample) => this.processRequest(codeExample));
  }

  processRequest(codeExample: CodeExample): void{
    this.codeExample = codeExample;
    console.log(codeExample.title); // correct data is returned

    //setTimeout(() => this.doSomethingWithDom(), 0); fixes the problem
    //this.doSomethingWithDom(); // Does NOT work because template is not updated
  }

  doSomethingWithDom(): void{
    // do something with dom here
  }
}

Upvotes: 0

Views: 861

Answers (2)

Tiep Phan
Tiep Phan

Reputation: 12596

maybe you add combine lifecycle ngAfterViewChecked() with a property like this:

export class CodeExampleDetailComponent implements OnInit, AfterViewChecked {
  // other properties
  private doIt = false;


  processRequest(codeExample: CodeExample): void{
    // other code
    this.doIt = true;
  }

  doSomethingWithDom(): void{
    // do something with dom here
    this.doIt = false;
  }
  ngAfterViewChecked() {
    if (this.doIt) this.doSomethingWithDom();
  }
}

note that ngAfterViewChecked() will call in every tick.

Upvotes: 1

Mohammed Sabbah
Mohammed Sabbah

Reputation: 883

Try this,

this.route.params
  .switchMap((params: Params) => this.codeExampleService.getCodeExample(+params['id']))
  .subscribe((codeExample: CodeExample) => { 
   this.processRequest(codeExample);
   this.doSomethingWithDom();});
}

Upvotes: 0

Related Questions