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

Time:11-03

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!

CodePudding user response:

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

CodePudding user response:

the ngOnInit() .detectChanges call is useless, because change detection is in progress and template will be checked just after ngOnInit hook is evaluated.

ngAfterViewInit and ngAfterContentChecked .detectChanges calls are just wrong, becase these hooks are called after the template is updated with the correct data.

  • Related