I have a material table that displays available options in the form of selects.
I have a root object which is the ngModel and serves to keep the options.
The options are retrieved from a database.
So lets say i have a root item of menu. This keep tracks of drinks and fruits in an array called snacks like so:
this.menu =
{
id: 1,
snacks: [
{ fruitId: 1, drinkId: 1, deleted: false },
{ fruitId: 2, drinkId: 2, deleted: false },
{ fruitId: 3, drinkId: 2, deleted: false },
{ fruitId: 3, drinkId: 2, deleted: true },
]
};
And then we define some fruits and drinks the user can choose:
this.fruits = [
{ id: 1, name: "Orange" },
{ id: 2, name: "Apple" },
{ id: 3, name: "Banana" },
{ id: 4, name: "Dragon fruit" }
];
this.drinks = [
{ id: 1, name: "Milk" },
{ id: 2, name: "Water" },
{ id: 3, name: "Juice" },
{ id: 4, name: "Soda" }
];
Then we map those in the table:
<table mat-table [dataSource]="menuTableSource" #menuTable>
<ng-container matColumnDef="fruit">
<th mat-header-cell *matHeaderCellDef> Fruit </th>
<td mat-cell *matCellDef="let menuItem; let i = index;">
<mat-select [(ngModel)]="menu.snacks[i].fruitId" name="fruitId"
#fruitId="ngModel">
<mat-option *ngFor="let fruit of fruits" [value]="fruit.id">
{{ fruit.name }}
</mat-option>
</mat-select>
</td>
</ng-container>
<ng-container matColumnDef="drink">
<th mat-header-cell *matHeaderCellDef> Drink </th>
<td mat-cell *matCellDef="let menuItem; let i = index;">
<mat-select [(ngModel)]="menu.snacks[i].drinkId"
name="drinkId" required>
<mat-option *ngFor="let drink of drinks" [value]="drink.id">
{{drink.name}}
</mat-option>
</mat-select>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="menuTableColumns"></tr>
<tr mat-row *matRowDef="let row; columns: menuTableColumns;"></tr>
</table>
Upon removing an item from this array and setting the table source data to this and calling renderRows() the table will drop the last entry even though the array of snacks is updated as expected.
onRemoveMenuItem(menuItem: any): void {
const idx = this.menu.snacks.indexOf(menuItem);
if (idx >= 0) {
this.menu.snacks[idx].deleted = true;
this.menuTableSource.data = this.menu.snacks.filter(x => !x.deleted);
this.menuTable.renderRows();
}
}
Is this a bug or do I have to update the table in some other way?
Please see this stackblitz which demonstrates the isssue: https://stackblitz.com/edit/angular-bzdjhj