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.

1 Answer 1

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

Sign up to request clarification or add additional context in comments.

2 Comments

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.
That's no problem. Glad it helped

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.