How to get the dimension of dynamic rendered eleme

2020-03-26 08:30发布

问题:

just imagine: 1. in component.html, you have

<div id = "myDiv">
      <p>{{text}}</p>
<div>
<button (click)="changeText()">changeText</button>
  1. in component.css / we do not set the height of div explicitly. The height of div depends on the height of p element. In other words, the number of words inside p decides the height of div

  2. in component.ts there is a function, which we can call it anytime and set the {{text}} property. So the div and p get rendered at runtime and dynamically. Like:

export class someComponent implements OnInit {

  constructor(private el: ElementRef) { }

  ngOnInit() {
  }

  changeText() {
    this.text = 'blablablabla.....';
    let divEl = this.el.nativeElement.querySelector('#myDiv');
    divEl.clientHeight/ or offsetHeight or/ getComputedStyle (can not get the correct value here!)
  }
}

Q: how can we get the actual height of the div after I change the text. (I can get the element by ElementRef) I have tried .offsetHeight, .clientHeight, .getComputedStyle.height....// It seems like all of them return the original value, not the actual value at runtime.

回答1:

In most cases, you don't need to set the height of the div container in code. It automatically adjusts to its content and can be fine-tuned with CSS style attributes.

But if you want to do some special calculations with the paragraph height to set the height of the div, you can do it with data binding (using the element.offsetHeight property in the calculations):

<div [style.height.px]="calculateDivHeight(paragraph)">
    <p #paragraph>{{text}}</p>
<div>
<button (click)="changeText()">changeText</button>
public calculateDivHeight(paragraph: HTMLElement): number {
    return doSomeProcessing(paragraph.offsetHeight);
}

Your current code could also work if you force change detection (see this answer) just after changing the paragraph content:

import { ApplicationRef } from '@angular/core';

constructor(private applicationRef: ApplicationRef, ...) {
  ...
}

changeText() {
  this.text = 'blablablabla.....';
  this.applicationRef.tick();
  let divEl = this.el.nativeElement.querySelector('#myDiv');
  ...
}


回答2:

It returns the previous values because it takes time for the browser to compute the new style.

The RequestAnimationFrame API is what you are looking for.

Once you've set the new text, use the RequestAnimationFrameAPI, it's a callback triggered once the browser is ready, basically when its render queue is empty.

this.text = "blablablabla...."
window.requestAnimationFrame(() => {
  // access the new css values here
})