Search code examples
angularangular2-changedetectionngzone

Angular 2 Lifecycle Hooks, change detection and ngZone


I have an Angular app where the user presses a button and trigger an animation. Basically it's two pictures switching with each other to create a running illusion.

At first my character is still then as we start to play, its pictures animate, but as it animates I get:

ExpressionChangedAfterItHasBeenCheckedError

My html:

<img [src]="isPlaying == false ? 'https://i.ibb.co/LgqQqFn/dino-1.png' : run()"/>

<button (click)="play()">Run</button>

My Ts:

  isPlaying: boolean = false;
  rightFoot: boolean = true;

  play() {        
    this.isPlaying = !this.isPlaying
    setInterval(() => {this.run()}, 200);
  }

  run() {       
    this.rightFoot = !this.rightFoot;
    if (this.rightFoot == false) {
      return 'https://i.ibb.co/JtQm93b/dino-3.png';
    } else {
      return 'https://i.ibb.co/x3JdgFf/dino-4.png';
    }
  }
}

My error code:

Error: NG0100: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value for 'src': 'https://i.ibb.co/JtQm93b/dino-3.png'. Current value: 'https://i.ibb.co/x3JdgFf/dino-4.png'..

I understand it has something to do with change detection. I have read documentation about ngZone, how it can track changes with setInterval() and I added it in my code but with no sucess :

play() {    
    this.isPlaying = !this.isPlaying
    this.ngZone.run(() => {
      setInterval(() => {this.run()}, 200);})
  }

This is a working StackBlitz of my issue. How should I implement ngZone so I don't get the ExpressionChangedAfterItHasBeenCheckedError anymore?


Solution

  • It is happening as the run method is trying to change image path in the same change detection cycle. it is being invoked from template as well as from the component:

    I have modified your code to fix this issue, please check the below stackblitz:

    https://stackblitz.com/edit/angular-ivy-rupneh?file=src/app/app.component.ts