Angular2: *ngFor does not update when array is upd

2020-06-07 06:45发布

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.

7条回答
我想做一个坏孩纸
2楼-- · 2020-06-07 07:15

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;
}
查看更多
相关推荐>>
3楼-- · 2020-06-07 07:15

late to the game but creating a deep clone using lodash worked for me

this.arr = cloneDeep(this.arr);

https://lodash.com/docs/4.17.15#cloneDeep

查看更多
时光不老,我们不散
4楼-- · 2020-06-07 07:21

Incase anyone else runs into my situation, make sure that the component that is updating is the same copy as the one being rendered.

I was using @ViewChild(MyComponent, { static: true }) private test: MyComponent to pass data to the component with the ngfor. (In my case that ended up locking onto another copy I didn't know about)

I was able to fix it by adding the attribute #mycomp to my component tag in the html and changing the above to @ViewChild('mycomp', { static: true }) private test: MyComponent

查看更多
爷的心禁止访问
5楼-- · 2020-06-07 07:24

Try creating a deep copy by doing

this.arr = Object.assign({}, NEW_VALUE);
查看更多
霸刀☆藐视天下
6楼-- · 2020-06-07 07:30
  1. Check if your component is configured with changeDetection:cHangeDetectionStrategy.OnPush, if you are going this then after updation of array you have to call changeDetectorRef.markForCheck()
  2. You can also implement onChange lifecycle hook and change values of array inside this function.
查看更多
混吃等死
7楼-- · 2020-06-07 07:32

I solved this error by adding a changDetection directive on @component as follows

    @Component({
      selector: 'app-page',
      templateUrl: './page.component.html',
      styleUrls: ['./page.component.scss'],
      changeDetection: ChangeDetectionStrategy.Default
    })

You also need to import it

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

There are two strategies onPush and Default

The onPush uses the CheckOnce strategy, meaning that automatic change detection is deactivated until reactivated by setting the strategy to Default (CheckAlways). Change detection can still be explictly invoked.

while the Default uses the CheckAlways strategy, in which change detection is automatic until explicitly deactivated.

Source Docs

查看更多
登录 后发表回答