Currently, I am facing an issue with detecting changes in Angular component Input variables. The specific variable I am dealing with is an array of objects where I need to pinpoint which object is changing and which property within that object is being modified. This detection is crucial as it dictates the behavior of form controls within a child component controlled by a parent component.
I have experimented with several solutions including:
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);
});
}
Despite my efforts, the function .create necessitates a TrackByFunction parameter, making it impossible to assign this.objDiffer[elt] due to its nature as an object rather than 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);
});
}
});
}
Although this method helps identify the changed value, it fails to provide information about the specific object that experienced the change.
export class ArrayWatchDemoComponent implements DoCheck {
@Input() datasource: Array<any> = [];
differ: any;
constructor(differs: IterableDiffers) {
this.differ = differs.find([]).create(null);
}
ngDoCheck() {
const change = this.differ.diff(this.datasource);
console.log(change);
}
This approach only outputs null values in the console, even though it responds to property changes within the input object array. Utilizing forEachAddedItem or forEachRemovedItem did not resolve this limitation.
@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);
});
}
}
}
My most recent attempt involved implementing the above code but encountered the following 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 also tried resetting the array content like so:
//this.list = [{foo: true}];
this.list = [];
this.list = [{foo: false}];
However, this proved to be a cumbersome solution that caused flickering elements in the child component.
In summary, my objective is for the child component to effectively detect changes within an object located in an input array provided by the parent component. Unfortunately, the current implementation falls short in achieving this goal