Suppose you have a parent component A and a child component B. The A component has a name and text properties. In its template it uses the expression that references name property:
template: '<span>{{name}}</span>'
And it also has B component in its template and passes the text property to this component through input property binding:
@Component({
selector: 'a-comp',
template: `
<span>{{name}}</span>
<b-comp [text]="text"></b-comp>
`
})
export class AComponent {
name = 'I am A component';
text = 'A message for the child component`;
...
}
So here is what happens when Angular runs change detection. It starts by checking A component. The first operation in the list is to update bindings so it evaluates text expression to A message for the child component and passes it down to the B component.It also stores this value on the view:
view.oldValues[0] = 'A message for the child component';
Then it calls the lifecycle hooks mentioned in the list.
Now, it performs the third operation and evaluates the expression {{name}}to the text I am A component. It updates the DOM with this value and puts the evaluated value to the oldValues:
view.oldValues[1] = 'I am A component';
Then Angular performs the next operation and runs the same check for the child B component. Once the B component is checked the current digest loop is finished.
If Angular is running in the development mode it then runs the second digest performing verification operations I listed above. Now imagine that somehow the property text was updated on the A component to the updated text after Angular passed the value A message for the child component to the B component and stored it. So it now runs the verification digest and the first operation is to check that the property text is not changed:
AComponentView.instance.text === view.oldValues[0]; // false
'A message for the child component' === 'updated text'; // false
Yet it has and so Angular throws the error ExpressionChangedAfterItHasBeenCheckedError.
The same holds for the third operation. If the name property was updated after it was rendered in the DOM and stored we’ll get the same error:
AComponentView.instance.name === view.oldValues[1]; // false
'I am A component' === 'updated name'; // false
so the error can be resolved by forcing change detection by:
ngAfterViewInit() {
this.cd.detectChanges();
}
taken from the link: https://indepth.dev/everything-you-need-to-know-about-the-expressionchangedafterithasbeencheckederror-error/