I'm relatively new to Angular so please forgive my may be trivial question.
I've also googled a lot, found a lot of similar questions, but none really addressing my problem.
Situation
Let's assume the following component's template:
<div class="wrapper">
<!-- Stuff -->
.
.
.
<div *ngFor="let group of groups">
<button #btn (click)="onClick(btn, group)">Change group title</button>
<div class="group-title">
{{group.title | translate}}
</div>
.
.
.
<div *ngFor="let item of group.subGroup">
{{item.title}}
.
.
.
</div>
</div>
<div/>
Now I want the user to be able to trigger a series of actions/events that eventually change the title of a single Group (single item in ngFor).
I.e.
onClick(btnRef, group) {
.
.
.
anAsyncronousEvent.subscribe(
success => group.title = success.BrandNewTitle;
)
}
Desired outcome
The DOM should display the new title of the affected group, but it doesn't. I've also tried without the 'translate' pipe, but in vain.
By googling around, I seem to understand that a change in DOM is detected by Angular only by looking at object reference used to generate the ngFor items, so that if I change only some internal property of the Object/Item, a ChangeEvent is not triggered.
Possibile solutions
One idea could be to make a deep copy of the Group Object and replace the corresponding item in the array behind the ngFor, but that would cripple the whole mess of making Angular refresh DOM only for what is really changed. Another idea could be to use markForCheck() but here I have two choices:
1) Use markForCheck() in the clickHandler but, again, this would trigger re-rendering for all groups in the component.
2) I could somehow create a subcomponent only for the group title but it seems to me kind of an overkill, and I'm also not sure it would work.
So, how do I force Angular to refresh ONLY the group title?
Thank you all in advance
EDIT
Ok. Probably the code posted above is a bit oversimplified.
This one here is closer to my real world app and is running on stackblitz here, where it reproduces the problem I'm trying to solve.
// Template
<div class="wrapper">
<div *ngFor="let group of groups">
<button #btn (click)="onClick(btn, group)">Pop away item</button>
<div class="group-title">
Group info: count = {{group.info | format}}
</div>
<div *ngFor="let item of group.items">
Item title: "{{item.title}}"
</div>
</div>
</div>
//Component
onClick(btn, group: any) {
setTimeout(() => { // In the real App this is an Observable
let i = this.groups.indexOf(group);
group.items.pop();
group.info.count--;
}, 1000);
}
I'm expecting the items count to be show decreased after button click, but it is not.
trackBy
– VikasngFor
by default tracks list items using object identity if you generate new object with same title angular will pick up the changes and it would re-create DOM but withtrackBy
it would just update the DOM rather than destroying and re-creating it – Vikas