5

I have angular component with array of Objects

export class AlertsConfigListComponent implements OnInit, DoCheck {
@Input() config: ProductAlertConfig[];

And using IterableDiffer to get changes of this array: constructor(private iterableDiffers: IterableDiffers) { this.iterableDiffer = iterableDiffers.find([]).create(null); }

ngDoCheck(): void {
let changes : IterableChanges<ProductAlertConfig> = this.iterableDiffer.diff(this.config);
if (changes) {
  this.doSmth();
}

}

It works and I can get changes every time when array is changed. So now my question is. How to check in changes object that array's size is changed, because it is triggered also when I sort this array. There are no properties in IterableChanges object for this purpose.

If I could get new size of array I would do that:

ngDoCheck(): void {
let changes : IterableChanges<ProductAlertConfig> = this.iterableDiffer.diff(this.config);
if (changes && newSize !== oldSize) {
  this.doSmth();
}

}

And it would fix the problem, but are there any other solutions?

2 Answers2

2

I am not sure if there is a direct method. One workaround would be to check if there are elements added/removed to the array by abusing forEachAddedItem and forEachRemovedItem methods and try/catch block. Try the following

ngDoCheck(): void {
  let changes: IterableChanges<ProductAlertConfig> = this.iterableDiffer.diff(this.config);
  let lengthChanged: boolean = false;

  if (changes) {
    try {
      changes.forEachAddedItem(item => {
        if (item) {
          lengthChanged = true;
          throw 'Array length changed';           // break from the `forEach`
        }
      });

      if (!lengthChanged) {                       // proceed only if `lengthChanged` is still `false`
        changes.forEachRemovedItem(item => {
          if (item) {
            lengthChanged = true;
            throw 'Array length changed';         // break from the `forEach`
          }
        });
      }
    } catch (e) {
      // pass
    }

    if (lengthChanged) {
      this.doSmth();
    }
  }
}

Try/catch is used here deliberately to break from the forEach. Commenting about it would help others/later

ruth
  • 29,535
  • 4
  • 30
  • 57
1

Problem is with your constructor.

constructor(private iterableDiffers: IterableDiffers){
   this.iterableDiffer = iterableDiffers.find(this.config).create()
}

Working Stackblitz :- https://stackblitz.com/edit/angular-uqivci

Aakash Garg
  • 10,649
  • 2
  • 7
  • 25
  • It is working fine. But my question is inside ngDoCheck() how can I check that size of array is changed. I mean Item is added or item is removed but skip this check for the time when we first time initialize array with values – Тарас Предзимирський May 28 '20 at 11:51
  • on push and pop its working, you need on length change? if a element is getting added or removed. that means length is changing. can you give a example what do you want? – Aakash Garg May 28 '20 at 11:58
  • like in my above example i have callback to eachaddeditem, you can add to eachremoveditem. in these callbacks you get your array length? Previous Array length will be current length - number of items you receive in callback? – Aakash Garg May 28 '20 at 12:15