Itai
Itai

Reputation: 417

Why a ViewChild ElementRef has 0 width and height in ngAfterViewInit?

I'm trying to do some calculations based on element width and height, but for some reason, those are not immediately available on the AfterViewInit lifecycle hook (both are 0).
Though setTimeout does seem to do the trick, I don't like it.

What causing this? Is there a more elegant solution?

@ViewChild('main') mainDiv: ElementRef;

ngAfterViewInit() {

  this.printMainHeight() // 0

  // with setTimeout width is correctly retrieved ...

  setTimeout(() => this.printMainHeight()) // 430

}

printMainHeight() {

  console.log(this.mainDiv.nativeElement.getBoundingClientRect().height)     

}

HTML

<div class"main" #main>
  <app-toolbar></app-toolbar>
  <app-list></app-list>
</div>

Upvotes: 8

Views: 3454

Answers (2)

StepUp
StepUp

Reputation: 38209

It is necessary to use ngAfterViewChecked lifecycle hook , not ngAfterViewInit. As Angular docs says about ngAfterViewChecked():

Respond after Angular checks the component's views and child views / the view that a directive is in.

Called after the ngAfterViewInit() and every subsequent ngAfterContentChecked().

Upvotes: 3

Daniel Pi&#241;eiro
Daniel Pi&#241;eiro

Reputation: 3159

That should work unless you have any asynchronous changes in your template in the <app-toolbar> or the <app-list>.

You can check the example here:

https://stackblitz.com/edit/angular-stack-afterviewinit-55563149?file=src%2Fapp%2Fapp.component.ts

If you see this example, the #mainDiv make changes after it was rendered (setTimeout in this example, but it can be anything async, like subscriptions and ajax request) meanwhile the #syncDiv load everything synchronous.

Upvotes: 0

Related Questions