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?
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