Good answers. However, it appears to me, that when I am using:
ChangeDetectorRef and AfterViewInit,
Angular gets into a few extra rendering cycles and if my HTML code is not designed with really good care or has a need for several calls to functions in the TS code that depend on the refresh, I get extra calls for the view rendering, thus extra processing.
Here is a solution I like using, because I do not have to worry about any of that, it is programmatically very simple, and requires nothing much extra from me or the system. I use it with no issues whenever Angular gives me hard time with the infamous error: "Expression has changed after it was checked".
I have this little public/exported function, which simply passes my value through a zero delay Promise. What that does, it forces JavaScript/JS into another background cycle, thus separating the value update into next processing cycle, and - preventing the error. (Note that the JS cycle is not the same as the Angular HTML view rendering cycle and is less processing intensive).
export async function delayValue(v: any, timeOutMs: number = 0): Promise<any> {
return new Promise((resolve) => {
setTimeout(() => {
resolve(v);
}, timeOutMs);
});
}
Now, when I need to prevent the error, I simply do:
this.myClassValue = await delayValue(newValue);
which is just one line of code. There really is no notable delay since the value of timeOutMs = 0.
Here is a typical scenario:
myObservable$.subscribe(newValue = {
... // WHEN NEW VALUE ARRIVES FROM NOTIFIER(S)
this.handleSubscribedValues(newValue);
...
});
// THIS MAY GIVE YOU THE ERROR !
private handleSubscribedValues(newValue) {
this.myClassValue = newValue;
}
// SO, USE THIS INSTEAD TO AVOID THE ERROR
private async handleSubscribedValues(newValue) {
this.myClassValue = await delayValue(newValue);
}
You can also use the delayValue() function with some delay/timeout value if you need to wait a bit for something to happen, e.g. give user a few seconds.
Hopefully, this will be useful to some of you.