chris01
chris01

Reputation: 12321

Angular: How to get rid of ExpressionChangedAfterItHasBeenCheckedError

I have this little sample of a select-box that is generated by the content of a Map.

https://stackblitz.com/edit/angular-mqccjn

Class

public map : Map <string, string> = new Map <string, string> ([
    [ "NEW", "?" ],
    [ "ACCEPTED", "&#10003;" ],
    [ "DECLINED", "&#10005;" ]
]);

Component

<select>
        <option *ngFor="let m of map.keys()" [innerHTML]="map.get(m)"></option>
</select>

I do not know why I get this Java Runtime Exception.

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngForOf: [object Map Iterator]'. Current value: 'ngForOf: [object Map Iterator]'."

Upvotes: 0

Views: 348

Answers (1)

Poul Kruijt
Poul Kruijt

Reputation: 71891

It will re-evaluate the map.keys() on every cycle, causing it to get a new object every time. You better store this immediately somewhere like this:

public map : Map <string, string> = new Map <string, string> ([
    [ "NEW", "?" ],
    [ "ACCEPTED", "&#10003;" ],
    [ "DECLINED", "&#10005;" ]
]);

public mapEntries = Array.from(this.map.entries());

and your template:

<select>
  <option *ngFor="let m of mapEntries" [value]="m[0]">{{m[1]}}</option>
</select>

Another way is to keep it like you had, and use the OnPush change detection strategy, which is anyways recommended for performance reasons:

import { Component, ChangeDetectionStrategy } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent  {}

Upvotes: 2

Related Questions