3

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.

好吃仙人
  • 137
  • 1
  • 10
  • 1
    `element.offsetHeight` should return the actual height of the element, but probably not in the execution cycle where the content is changed, unless you force Angular change detection. Please show the code and markup where you want to use the height of the `p` element. – ConnorsFan Dec 13 '17 at 19:03
  • 1
    @ConnorsFan, question updated – 好吃仙人 Dec 13 '17 at 19:28

2 Answers2

5

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');
  ...
}
ConnorsFan
  • 70,558
  • 13
  • 122
  • 146
  • Actually, I do want to do calculations(use it for some animation) based on the chaning div Hieght..// I set div width = 200px for example and the height of div will be adjusted based the p element. // – 好吃仙人 Dec 13 '17 at 19:54
  • You can adapt `doSomeProcessing()` to meet your needs. – ConnorsFan Dec 13 '17 at 20:00
  • one possible flaw in this method is that calculateDivHeight() function will be called every time when change detection starts, which means every asynchronous function (click, settimeout, ajax request) will trigger change detection which will then trigger this function – 好吃仙人 Dec 14 '17 at 17:07
  • One alternative would be to use your original code and to force change detection, for example with `ApplicationRef.tick()`. I added more details in the answer. – ConnorsFan Dec 14 '17 at 17:38
-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
})
Ploppy
  • 14,810
  • 6
  • 41
  • 58