Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2: *ngFor does not update when array is updated

I have an array of objects (let's call it arr). In one of my component's inputs in the (change) method I modify one of these object's attribute, but in the view (*ngFor) nothing changes. I read that Angular2 change detection doesn't check the contents of arrays or object, so I tried these:

this.arr = this.arr.slice(); 

and

this.arr = [...this.arr]; 

But the view doesn't change, it still shows the old attribute. In the (change) method with console.log() I got the correct array. Weird, but this one works: this.arr = []; I tried NgZone and markForCheck() too.

like image 619
Roland Rácz Avatar asked Jul 21 '17 14:07

Roland Rácz


2 Answers

You could also use the trackBy option in your *ngFor expression, providing a unique ID for every item inside the array. This does make you 100% responsible for change detection, so update this (unique) property every time the item in the array changes. Angular will then only re-render the list if any item inside your array has been given a different trackBy property:

*ngFor="let item of (itemList$ | async); trackBy: trackItem" 

or:

*ngFor="let item of itemList; trackBy: trackItem" 

where:

trackItem is a public method in your component:

public trackItem (index: number, item: Item) {   return item.trackId; } 
like image 153
Michael Trouw Avatar answered Oct 04 '22 14:10

Michael Trouw


Since you mentioned that you already tried markForCheck(), you should try detectChanges instead (that just what worked for me and markForCheck did not work). For those that need the steps:

Add ChangeDetectorRef to your imports:

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

Add ChangeDetectorRef to your constructor:

constructor(     private changeDetection: ChangeDetectorRef   ) { } 

Then on the next line after you update the array:

this.changeDetection.detectChanges(); 
like image 40
Kyle Krzeski Avatar answered Oct 04 '22 15:10

Kyle Krzeski