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
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.
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.
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.
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.
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 differ
s 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With