Debugging and Understanding
ExpressionHasChangedAfterChecked

September 2020

What's going on?

Angular has a LifeCycle Management according to which it will update the a components class and view. It starts with ngOnChanges, then progresses to ngOnInit (which only runs once), and then progresses to ngAfterViewInit (also only running once). I've not listed all lifecycle hooks here, to see the full list check https://angular.io/guide/lifecycle-hooks.

Now what Angular doesn't like is if you mess with class properties you're also referencing in the view (= the html) inside of ngAfterViewInit or ngAfterViewChecked. The reason for this is that Angular has already set up the html and doesn't want to check everything again. If you're doing that, Angular will throw a ExpressionChangedAfterItHasBeenCheckedError error and will not update the view for you. So what can you do to mitigate the problem?

Use the ChangeDetectorRef

If you're using an ngAfterViewInit, you can try to solve the problem by letting Angular know it needs to check for changes again. Just add the following code to your class:

import { Component, OnInit, AfterViewInit, ViewChild, ElementRef, ChangeDetectorRef } from '@angular/core';

@Component({
  selector: 'my-app',
  template: ``
})
export class AppComponent  {
  
  someProperty = 0;

  constructor(
    private cdr: ChangeDetectorRef
  ) {}

  ngAfterViewInit() {
    this.someProperty = 1;
    this.cdr.detectChanges();
  }

}

You can find this code on Stackblitz here:
https://stackblitz.com/edit/angular-use-cdr-to-mitigate-expressionhaschangedafterchecked?file=src/app/app.component.ts

Find the problematic "expression" aka class property

Often you'll know by looking at the error message which property Angular is talking about. For example if Angular says:

ERROR

Error: ExpressionChangedAfterItHasBeenCheckedError:
Expression has changed after it was checked. Previous value: '5'. Current value: '6'.

You'll know, "aha, it was the property I initialized with the value 5" and you'll know which one this is.

If you don't know immediately which property Angular is talking about you can try the following things to find it:

Those methods should help you to isolate and track down the problematic expression.

Conclusion

An error message identifier with 43 characters might scare you first. But after understanding the lifecycle methods, you also understand this error better and that it's actually not that hard to debug.

Dear Devs: You can help Ukraine🇺🇦. I opted for (a) this message and (b) a geo targeted message to Russians coming to this page. If you have a blog, you could do something similar, or you can link to a donations page. If you don't have one, you could think about launching a page with uncensored news and spread it on Russian forums or even Google Review. Or hack some russian servers. Get creative. #StandWithUkraine 🇺🇦
Dear russians🇷🇺. I am a peace loving person from Switzerland🇨🇭. It is without a doubt in my mind, that your president, Vladimir Putin, has started a war that causes death and suffering for Ukrainians🇺🇦 and Russians🇷🇺. Your media is full of lies. Lies about the casualties, about the intentions, about the "Nazi Regime" in Ukraine. Please help to mobilize your people against your leader. I know it's dangerous for you, but it must be done!