Everything you need to know about the `ExpressionChangedAfterItHasBeenCheckedError` error
Max NgWizard K
4.2K43

Thank you very much for this great explanation.

My situation is similar to the one you described under your “Shared service” section. Following are the relevant details.

I am using “named outlets” to load my components:

const appRoutes: Routes = [
// Layout 1: Launch
{ path: 'launch', children: [
{ path: '', component: LaunchComponent }
]},
// Layout 2: Main Layout
{ path: '', children: [
{ path: '', component: LoadingComponent, outlet: 'loading' },
{ path: '', component: HeaderComponent, outlet: 'header' },
{ path: '', component: MainComponent }
]},
// Catch All
{ path: '**', redirectTo: '' }
];

The LoadingComponent displays a loading spinner and overlays the page to block user input. The HeaderComponent uses a shared service (called CommonService) to let the LoadingComponent know when it is done loading, so that the LoadingComponent will hide itself. Here is the ngOnInit method in the HeaderComponent:

constructor(commonService: CommonService,
private dataService: DataService) { }

ngOnInit() {
// Display the loading overlay.
this.commonService.registerWait();

// Get patient and calculator data.
Observable.forkJoin([
this.dataService.getPatient(),
this.dataService.getCalculators()
])
.subscribe(
(response => {
this.patientVM = response[0];
this.calculators = response[1];

// Let the loading page know that we are done.
this.commonService.unregisterWait();
})
);
}

And, here is the ngOnInit method in the LoadingComponent:

constructor(private commonService: CommonService) { }

ngOnInit() {
this.waitingOnChanged = this.commonService.waitingOnChanged
.subscribe(
(waitingOn: number) => {
// If we are waiting on async processes to complete, display the loading page.
// Otherwise, hide it.

// THIS CAUSES ExpressionChangedAfterItHasBeenCheckedError
// this.isLoading = waitingOn > 0;

// THIS WORKS
Promise.resolve(null).then(() => this.isLoading = waitingOn > 0);
}
);

// Determine whether or not to initially display the loading page,
// depending on whether or not we are waiting on async processes to complete.
this.isLoading = this.commonService.waitingOn > 0;
}

You can see that using the following code gets around the ExpressionChangedAfterItHasBeenCheckedError issue:

Promise.resolve(null).then(() => this.isLoading = waitingOn > 0);

But, you would not recommend this, correct? What is a better solution? Thank you!

Like what you read? Give Steve Clark a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.