Search code examples
angulargoogle-chromedata-bindingdirectivechange-detector-ref

How to solve the "Expression Changed After It Has Been Checked Error" in Angular?


I want to implement a Chat in Angular. Every item (message) of the chat has a header (title/name) which should have a specific margin. The margin should be calculated based on the height of the div. The code looks like this.

<div *ngFor="let item of chatArray">
  <div #juliet [style.margin-top.px]= "-(juliet.clientHeight/2)">
  {{item.message}}
  </div>
</div>

The problem is in the Chrome browser (no issues in Mozilla). The Console error is: "ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'margin-top: -40.5'. Current value: 'margin-top: -40'.".

In the ts file I tried to implement the change detection:

ngOnInit() {
//code for chat initialization
this.cdRef.detectChanges();
}

ngAfterViewInit() {
   this.cdRef.detectChanges();
}

ngAfterContentChecked() {
  this.cdRef.detectChanges();
}

If I add in the .ts file

@Component({
  ...
  changeDetection: ChangeDetectionStrategy.OnPush
})

the error disappears but the margin is less than it should be. I would like to get rid of the error and to calculate the right margin based on the div height.

I would appreciate a lot any ideas you have. Thank you!


Solution

  • Something to try, might get around this issue. Create a directive

    import { Directive, ElementRef } from '@angular/core';
    
    @Directive({
      selector: '[appApplyMargin]'
    })
    export class ApplyMargin {
        constructor(el: ElementRef) {
           el.nativeElement.style.marginTop = 
                  (el.nativeElement.clientHeight/2) + 'px'
        }
    }
    

    Note: if needs be wrap the code in the constructor in a setTimeout