Reputation: 7200
I am reading this small article. Article says:
If you need at some point to change the data in the collection, for example as a result of an API request, we have a problem because Angular can’t keep track of items in the collection and has no knowledge of which items have been removed or added.
As a result, Angular needs to remove all the DOM elements that associated with the data and create them again.
Note: when I’m saying “change the data” I’m referring to replace the collection with new objects and not keeping the same reference.
I tried to check if this. My code is following (stackblitz):
html
<button (click)="changeObjItems()">Change Items array</button>
<app-item *ngFor="let i of objItems" [val]="i.item.id"></app-item>//line 2
Typescript
objItems = [
{item: {id:1}},
{item: {id:1}},
{item: {id:1}},
{item: {id:1}}
];
changeObjItems(){
this.objItems[3] = {item:{id: Math.random()}};
this.objItems = [...this.objItems];//shallow clone
}
So basically in line 2, I am iterating over an array nested object (objItems
) and created a new component (app-item
) on each iteration. Later I am changing the data of the array (by changeObjItems()
) and checking if all the previous components are destroyed by logging into onDestroy of app-item
.
However, after running changeObjItems()
, console shows that *ngFor is only destroying the component for which data has been changed. But as per article, I was expecting all components to be destroyed.
What am I missing here?
Upvotes: 2
Views: 1350
Reputation: 54741
You need to clone all objects in the array to trick change detection in ngFor.
this.objItems[3] = {item:{id: Math.random()}};
this.objItems = this.objItems.map(obj => {...obj});
Cloning/slicing the array itself has no effect, because ngFor is tracking the contents of the array against each DOM element. It remembers what value was previously used for DOM element, and if that value has not changed it will not recreate the DOM element.
That can be a problem for items that mutate but represent the same data, and that is why ngFor has the trackBy callback which allows you to change what value is remembered for DOM elements.
Upvotes: 2