Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect changes in objects inside array in Angular2

Using Angular 2 and typescript. I have an array that I use DoCheck and IterableDiffer to listen to changes in my code. When the array is changed I get notifications, but when a property inside one of the objects in the array changes I don't get notified. I tried using KeyValueDiffer but it doesn't work. I think maybe I need to use the "_differs.find" differently. Any ideas?

@Component({
    selector: 'test'
})
@View({
    template: `
    <div>hello!</div>`
})
export class MyComponent implements DoCheck {

private _differ: IterableDiffer;
private _differ2: KeyValueDiffer;
_myItems: MyItem[];
@Input()
set myItems(value: MyItem[]) {
    this._myItems = value;

    if (!this._differ && value) {
        this._differ = this._iterableDiffers.find([]).create(null);
    }
    if (!this._differ2 && value) {
        this._differ2 = this._differs.find(this._myItems).create(null);
    }
}
get myItems() {
    return this._myItems;
}

constructor(private _iterableDiffers: IterableDiffers, private _differs: KeyValueDiffers, private _myService: MyService) {
    this.myItems = _myService.getItems();
}

ngDoCheck() {

    var changes = this._differ.diff(this._myItems);

    if (changes) {
        changes.forEachAddedItem((record) => {
            console.log('added ' + record.item);
        });
        changes.forEachRemovedItem((record) => {
            console.log('removed ' + record.item);
        });
    }

    var changes2 = this._differ2.diff(this._myItems);
    if (changes2) {
        changes2.forEachChangedItem(
            (record) => {
                    console.log(record.key + "," + record.currentValue);
                }
            });
    }
  }
}

There is no way to get notified on changes in one of the properties of MyItem

like image 543
Ido Avatar asked Mar 02 '16 13:03

Ido


People also ask

How do you find change in an array?

To detect changes in an array from an @input property with Angular, we can get the latest value in the ngDoCheck method. //... export class AppComponent implements OnInit { constructor(private iterableDiffers: IterableDiffers) { this. iterableDiffer = iterableDiffers.

How do you identify changes in Angular components?

To run the change detector manually: Inject ChangeDetectorRef service in the component. Use markForCheck in the subscription method to instruct Angular to check the component the next time change detectors run. On the ngOnDestroy() life cycle hook, unsubscribe from the observable.

How does change detection work in Angular?

Change detection works by detecting common browser events like mouse clicks, HTTP requests, and other types of events, and deciding if the view of each component needs to be updated or not.

How do you subscribe to an array?

Subscribe to changing array Instead of pushing values to the existing arrays, you push values to the Subject (which holds basically an array of the elements). When you push to the Subject, you generate an event that can be caught by a subscriber.


1 Answers

In fact, you need to check differences for each object in the list not on the list itself. KeyValueDiffer must be applied on an object not on an array.

You could initialize an object containing all these KeyValueDiffer instances for the elements of your array:

constructor(private differs:  KeyValueDiffers) {
}

ngOnInit() {
  this.objDiffer = {};
  this.list.forEach((elt) => {
    this.objDiffer[elt] = this.differs.find(elt).create(null);
  });
}

Within the ngDoCheck, you need then to iterate over the differs to check there are changes (for each item of the array):

ngDoCheck() {
  this.list.forEach(elt => {
    var objDiffer = this.objDiffer[elt];
    var objChanges = objDiffer.diff(elt);
    if (objChanges) {
      objChanges.forEachChangedItem((elt) => {
        if (elt.key === 'prop1') {
          this.doSomethingIfProp1Change();
        }
      });
    }
  });
}

See this plunkr: http://plnkr.co/edit/JV7xcMhAuupnSdwrd8XB?p=preview

Notice that I skipped the change detection for the array... But both can be done in parallel. Moreover when elements are added / removed the list of KeyValueDiffers should be updated accordingly.

like image 156
Thierry Templier Avatar answered Oct 15 '22 14:10

Thierry Templier