0

I'm trying to get an Angular component Input variable to detect changes. The input variable is a array of objects and I need to detect what object changes and what property that is changing. I'm using this to change behaviour of form controls in a child component from a parent component.

I've tried the following solutions:

Detect changes in objects inside array in Angular2

constructor(private differs:  KeyValueDiffers) {
}

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

However the function .create requires TrackByFunction and it's not possible to assign this.objDiffer[elt] since it's a object and not a list of objects.

Detect changes in objects inside array in Angular2

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

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

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

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);
        });
      }
    });
  }

This let's me get the value changed, but not the actually object that I'm looking for.

http://blog.bogdancarpean.com/how-to-watch-for-changes-an-arrayobject-on-angular-2/

export class ArrayWatchDemoComponent implements DoCheck {

  @Input() datasource: Array&lt;any&gt; = [];

  differ: any;

  constructor(differs: IterableDiffers) {
     this.differ = differs.find([]).create(null);
   }

  ngDoCheck() {
    const change = this.differ.diff(this.datasource);
    console.log(change);
  }

This solution is only console logging null values. But it triggers when I change the property of the object in the input array. I know you can use forEachAddedItem or forEachRemovedItem but this doesn't fix the solution.

https://www.concretepage.com/angular/angular-keyvaluediffers

@Input() empArray: Employee[];
empDifferMap = new Map<number, any>();
empMap = new Map<number, Employee>();
arrayDiffer: any;
constructor(private kvDiffers: KeyValueDiffers) {}
ngOnInit() {
    this.empArray.forEach(emp => {
      this.empDifferMap[emp.id] = this.kvDiffers.find(emp).create();
      this.empMap[emp.id] = emp;
    })
}
ngDoCheck() {
    for (let [key, empDiffer] of this.empDifferMap) {
      let empChanges = empDiffer.diff(this.empMap.get(key));
      if (empChanges) {
        empChanges.forEachChangedItem(record => {
          console.log('Previous value: ' + record.previousValue);
          console.log('Current value: ' + record.currentValue);
        });
      }
    }
} 

This was the recent one I've tried, but I didn't get it to work and got the error

"ERROR in src/app/forms/dynamic-form/dynamic-form.component.ts(39,34): error TS2569: Type 'Map' is not an array type or a string type. Use compiler option '--downlevelIteration' to allow iterating of iterators."

I've also tried to create the array again.

//this.list = [{foo: true}];
this.list = [];
this.list = [{foo: false}];

But that's a ugly solution and makes the elements in the child component flicker.

I expect the child component to detect changes in a object that is in a array which is a input. The child component doesn't detect changes.

mpro
  • 14,302
  • 5
  • 28
  • 43
hnkeh
  • 11
  • 1
  • 3

1 Answers1

0

I would highly recommend to user FormArray form Angular Reactive Forms. FormArray is a highly efficient method for detecting changes too. Find this link to start with FormArray starter

Bharath
  • 85
  • 1
  • 10
  • That's a good solution to the problem I'm having, might go this route instead - thanks. However it doesn't answer the question so I can't mark it as an answer. – hnkeh Nov 07 '19 at 09:29
  • That's no problem. Glad it helped – Bharath Nov 08 '19 at 11:19