Search code examples
javascriptangulariterableangular2-changedetection

Get array size changes in Angular 8 using IterableDiffer


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?


Solution

  • 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