Home > Back-end >  Angular NG0100: ExpressionChangedAfterItHasBeenCheckedError
Angular NG0100: ExpressionChangedAfterItHasBeenCheckedError

Time:01-06

I'm new to angular and run into a problem. Everything runs fine but the error "ExpressionChangedAfterItHasBeenCheckedError" appears.

I've implemented a custom CdkStepper. On a specific cdk-step I use a [completed] directive.

In this step I have a component which has a list:

class ListComponent {
    list: ListElement[];

    ngOnInit(): void {
        this.listService.loadList().subscribe(l => this.list = l);
    }
}

Now the completed state depends whether the list is empty or not:

<my-stepper>
    <cdk-step [completed]="listComponent.list.length > 0">
        <list #listComponent></list>
    </cdk-step>
</my-stepper>

As I run the program the ExpressionChangedAfterItHasBeenCheckedError appears but everything works fine. Should I detect changes manually in ngAfterViewInit()?

CodePudding user response:

There are a number of things with the above code that should be changed. My guess is that you are receiving this error due to this line this.list = this.listService.loadList().subscribe(l => this.list = l);. It assigns to the list property twice. If the service call is returning quickly, then that should cause your error.

This line is incorrect though and should at a minimum be updated to this.listService.loadList().subscribe(l => this.list = l);. Typescript shouldn't even allow what you have because you are assigning a Subscription to what is supposed to be a ListElement[]. Just updating it as I've stated though might not be enough, because technically the list property will start off with the undefined value and if the service is returning quickly, the value of list will be updated to the results of the service call and will cause the same issue.

I would recommend using the AsyncPipedocs. A few articles as to why this would be a better approach1, 2.

What would this look like with your example?

class ListComponent {
    list$: Observble<ListElement[]> = this.listService.loadList();
}
<my-stepper *ngIf="list$ | async as list">
    <cdk-step [completed]="list.length > 0">
        <list #listComponent></list>
    </cdk-step>
</my-stepper>
  • Related