Search code examples
angulartypescriptangular-componentsangular-changedetection

How to get size of a HTMLElement with variable text after changing text in Angular 7?


I have created a component with an input attribute text and a public property height. After changing text the height of the component should be computed and set to the heightproperty.

Problem: The HTML seems not to be rendered right after setting the text so that the height is 0. If I read the element's height in a setTimeout() call, I get the right height.

I uploaded the test project to StackBlitz: https://stackblitz.com/edit/angular-ivw9d7

What the app does is:

  1. Set text of testComponent with lorem ipsum.
  2. Get height right after setting the text and write it to the console.
  3. Get height right 2 seconds after setting the text and write it to the console.

In step 2. the height is 0, in step 3. the height is as it should be.


Solution

  • The text property of the TestComponent is bound to the testText property of AppComponent:

    <app-test-component #testComponent [text]="testText"></app-test-component>
    

    and you trigger change detection when the text property is modified in the TestComponent:

    @Input() set text(value: string) {
      this._text = value;
      this.cd.markForCheck();
      this.cd.detectChanges();
    }
    

    The problem is that when you modify testText in AppComponent, the text property setter in TestComponent will be called only at the next change detection cycle. You can elmininate the delay by forcing change detection as soon as testText is modified in AppComponent:

    this.testText = "Some new text";
    this.cd.detectChanges();
    console.log(`height right after changing is ${this.testComponent.height}`);
    

    To make sure that change detection is always triggered after modifying testText, you could define it as a getter/setter property, and call ChangeDetectorRef.detectChanges in the setter:

    public _testText = '';
    
    get testText(): string {
      return this._testText;
    }
    set testText(value: string) {
      this._testText = value;
      this.cd.detectChanges();
    }
    

    With that code in place, you don't need to force change detection in the TestComponent.

    See this stackblitz for a demo.