3

-------------- update ---------------

ChangeDetectorRef.detectChanges() run the change detectors for the component and its children. Thus, it might one solution.

-------------- original question ----------------

  1. Purpose: I want to get informed after a specific dom element is updated in a component.

    See the picture underneath: (change the text property will change the content of p, which in turn change the height of p element in dom) enter image description here

  2. Result: the clientHeight of p is still the previous value, not the newest one.

    Expected result: the newest value

  3. possible solutions:

    • I know ngAfterViewChecked will get fired every time in the change detection and it stands for the state after the view is updated.
    • Some walkaround solution for this problem can be force the change detection happens like: ApplicationRef.tick() or ChangeDetectorRef.detectChanges() (see the answer here: https://stackoverflow.com/a/34829089/7787645)

4. My confusions:

  • What I want is the state after a specific DOM element in a component get updated.
  • ngAfterViewChecked will get fired by every async functions(by default), which is not suitable here I think.
  • And ApplicationRef.tick() or ChangeDetectorRef.detectChanges() can force to trigger the change detection which will parse the whole component tree(from root to the child) which I think might be too costly.
  • I'm wondering whether there is some function like:

changeProperty(this.text => {
 this.text = 'A long long text';
 }).then( () => {
   // here is the state after the corresponding text is updated in the view
})

Or which is the right way to solve this problem here? Appreciate for any thoughts!

好吃仙人
  • 137
  • 1
  • 10
  • _`ngAfterViewChecked`... which is not suitable here I think_ - maybe consider it one more time. DOM is updated during change detection, and `ngAfterViewChecked` tells you when DOM finished updating. The solution by @smnbbrv although working in a browser, may not work on other platforms such as webworker, universal, nativescript etc. – Max Koretskyi Jan 07 '18 at 16:59
  • @AngularInDepth.com, I also agree with your idea, since **ngAfterViewChecked** get fired every time after change detection finished. For this problem, I just want to get the latest state of one DOM component. **ngAfterViewChecked** is too "big". One possible solution I have found is to use **ChangeDetectorRef.detectChanges()** to force the change detection to update the view in my async callback function, which means to force this process happens earlier. – 好吃仙人 Jan 08 '18 at 11:03
  • Right, I write in-depth about it in [Everything you need to know about change detection in Angular](https://blog.angularindepth.com/everything-you-need-to-know-about-change-detection-in-angular-8006c51d206f). The side effect is that it runs change detection for all components. Just an idea, if you're interested in one particular property, maybe consider using a directive to render it's value and pass the value into directive through input. – Max Koretskyi Jan 08 '18 at 11:54
  • @AngularInDepth.com, thanks for your idea, I will try it – 好吃仙人 Jan 08 '18 at 13:36

1 Answers1

1

There is nothing like that and I doubt it will ever appear.

However your particular problem can be solved in a totally different manner. As long as you want to control the way how your text / html gets rendered it is way easier to render it yourself.

Just set the innerHTML and the proper height will be in place

changeText(para) {
  para.innerHTML = 'long text';
  console.log(para.clientHeight);
}

and that's it. Remember that it may be better to use innerText or perform some HTML sanitizing before assigning it like that.

smnbbrv
  • 23,502
  • 9
  • 78
  • 109