Whatever I try, I just cannot seem to trigger change detection inside the template for an object that is part of an array of objects inside an array of objects. This is the (top) object structure:
export interface CompatibleCards {
appid: number,
banned: boolean,
items: { addedToTrade: boolean, appPosition: number, banned: boolean, classid: number, iconUrl: string, marketHashName: string, name: string, numberOfListings: number, position: number, price: number, quantity: number, type: string }[],
name: string,
numberOfCardsInBadge: number,
numberOfDifferentCards: number,
totalNumberOfItems: number
}
And here is the template:
<ng-container *ngIf="this.compatibleCards?.length else no_compatible_cards">
<h3>{{ numberOfCompatibleCards }} cartes compatibles</h3>
<div class="conteneur-ensembles">
<div *ngFor="let currentApp of compatibleCards" class="conteneur-ensemble-compatible">
<h3><a href="https://steamcommunity.com/id/raggart/gamecards/{{ currentApp.appid }}/" target="_blank">{{ currentApp.name }} ({{ currentApp.numberOfDifferentCards }} / {{ currentApp.numberOfCardsInBadge }} cards)</a></h3>
<div class="conteneur-images-cartes">
<span *ngFor="let currentItem of currentApp.items" title="{{ currentItem.name }}" [ngClass]="{ 'conteneur-carte': true, 'ajoute-echange': currentItem.addedToTrade }" (click)="ajouterRetirerObjetPourEchange(currentItem, 'ajouter')">
<img class="image-carte" src="http://cdn.steamcommunity.com/economy/image/{{ currentItem.iconUrl }}" alt="{{ currentItem.name }}" title="{{ currentItem.addedToTrade }}">
<span *ngIf="currentItem.price && currentItem.price > 0" class="prix-carte" title="{{ currentItem.name }}">{{ currentItem.price / 100 | currency }}</span>
<span *ngIf="currentApp.banned" class="prix-carte" title="{{ currentItem.name }}">--</span>
</span>
</div>
</div>
</div>
</ng-container>
As you can see, I am using the [ngClass] directive to populate the css classes based on the addedToTrade property of the CompatibleCards.items object. It populates properly, meaning that if I change the addedToTrade property before the first render, the class is present. However, when I try to update the object at a later time, using the code below, the template does not show or remove the class.
ajouterRetirerObjetPourEchange(objetAEchanger: any, operation : "ajouter" | "retirer") : void {
console.log(objetAEchanger);
if(operation == "ajouter") {
this.itemsForTrade.push({...objetAEchanger});
} else {
const positionObjetEchangeTrouve = this.itemsForTrade.findIndex((currentItem: any) => currentItem.classid == objetAEchanger.classid && currentItem.position == objetAEchanger.position);
this.itemsForTrade.splice(positionObjetEchangeTrouve, 1);
}
this.compatibleCards[objetAEchanger.appPosition].items[objetAEchanger.position].addedToTrade = ! this.compatibleCards[objetAEchanger.appPosition].items[objetAEchanger.position].addedToTrade;
// this.compatibleCards[objetAEchanger.appPosition].items = [].concat(this.compatibleCards[objetAEchanger.appPosition].items);
// this.compatibleCards = [].concat(this.compatibleCards);
}
Even reassigning the arrays with [].concat (or using spread [...this.compatibleCards] does not update the template (see the comments at the end of the function above).
Is there any way I can force my template to update itself after an update of an object inside the items array?