Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expression has changed after it was checked during iteration by map keys in angular 2

I don't understand why I get error. My map is not changed .

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

<tr *ngFor="let author of bindedAuthors.keys()">
  <td> {{author}}</td>
  <td>
    <button (click)="onUpdate(author)"
            class="btn gl-btn-primary">Update
    </button>
  </td>
  <td>
    <button (click)="onDelete(author)" class="btn gl-btn-default">Delete</button>
  </td>
</tr>

The result is expected, all data is shown but this error is flooding the console every time.

like image 597
Yurii Kozachok Avatar asked Nov 02 '17 15:11

Yurii Kozachok


3 Answers

Don't bind to a method ...keys() in the template. It will be called every time change detection runs. object.keys() returns a new object every time it is called and Angular recognizes this as an unexpected change, which leads to your error.

You can fix it like

someMethod() {
  this.bindedAuthorsKeys = this.bindedAuthors.keys();
}
*ngFor="let author of bindedAuthorsKeys"
like image 190
Günter Zöchbauer Avatar answered Oct 24 '22 19:10

Günter Zöchbauer


My map is the main source of the current data which is getting automatically synced from Firestore. If I do what is suggested in the accepted answer by Günter, I have to make sure to keep this array in sync with my map. Instead of this, I use the built-in keyvalue pipe of Angular directly with the map like follows:

<tr *ngFor="let author of bindedAuthors | keyvalue">
  <td> {{author.value}}</td>
  <td>
    <button (click)="onUpdate(author.value)"
            class="btn gl-btn-primary">Update
    </button>
  </td>
  <td>
    <button (click)="onDelete(author.value)" class="btn gl-btn-default">Delete</button>
  </td>
</tr>

Are there any caveats I am unaware of?

like image 26
Tas Avatar answered Oct 24 '22 18:10

Tas


I have tried the above solutions but only the below solution worked for me.

Hope it helps:

get getBindedAuthors(){
  return Array.from(bindedAuthors.keys());
}
<tr *ngFor="let author of getBindedAuthors">
  <td> {{author}}</td>
  <td>
    <button (click)="onUpdate(author)"
            class="btn gl-btn-primary">Update
    </button>
  </td>
  <td>
    <button (click)="onDelete(author)" class="btn gl-btn-default">Delete</button>
  </td>
</tr>
like image 37
Aman Goel Avatar answered Oct 24 '22 18:10

Aman Goel