简体   繁体   English

检测Angular2中数组内对象的更改

[英]Detect changes in objects inside array in Angular2

Using Angular 2 and typescript. 使用Angular 2和打字稿。 I have an array that I use DoCheck and IterableDiffer to listen to changes in my code. 我有一个数组,我使用DoCheck和IterableDiffer来监听我的代码中的更改。 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. 我尝试使用KeyValueDiffer,但它不起作用。 I think maybe I need to use the "_differs.find" differently. 我想也许我需要以不同方式使用“_differs.find”。 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 无法获得有关MyItem的某个属性更改的通知

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. KeyValueDiffer必须应用于不在数组上的对象。

You could initialize an object containing all these KeyValueDiffer instances for the elements of your array: 您可以初始化包含阵列元素的所有KeyValueDiffer实例的对象:

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 ,您需要迭代differ s来检查是否有更改(对于数组的每个项目):

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 看到这个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. 此外,当添加/删除元素时,应相应地更新KeyValueDiffers列表。

I found inspiration in Thierry Templiers answer but it did not work for me- I modified it and ended up with this solution: 我在Thierry Templiers的答案中找到了灵感,但它对我没有用 - 我修改了它并最终得到了这个解决方案:

You have this private variable: 你有这个私有变量:

 private objDiffers: Array<KeyValueDiffer<string, any>>;

You want to watch each element in an Array. 您想要观察数组中的每个元素。 In this case the array type is Array. 在这种情况下,数组类型是Array。 The constructor should look like this: 构造函数应如下所示:

  constructor(
    private differs: KeyValueDiffers) {
    this.itemGroups = new Array<ItemGroup>();
    this.differ = this.differs.find(this.itemGroups).create();
  }

ngOninit like this: 像这样的ngOninit:

  public ngOnInit(): void {
    this.objDiffers = new Array<KeyValueDiffer<string, any>>();
    this.itemGroups.forEach((itemGroup, index) => {
      this.objDiffers[index] = this.differs.find(itemGroup).create();
    });
  }

and ngDoCheck like this: 和ngDoCheck像这样:

ngDoCheck(): void {
    this.itemGroups.forEach((itemGroup, index) => {
      const objDiffer = this.objDiffers[index];
      const objChanges = objDiffer.diff(itemGroup);
      if (objChanges) {
        objChanges.forEachChangedItem((changedItem) => {
          console.log(changedItem.key);
        });
      }
    });
  }

Now you will notice that each time an item within the array changes you will get a console log with that item and with the property that has changed. 现在您将注意到,每次数组中的项目发生更改时,您将获得包含该项目的控制台日志以及已更改的属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM