Issue
I have a shopping cart that I am implementing through an Angular Material table. Each row has a picture, description,…, and delete button. The problem is that when I click on the delete button the row does not disappear until all items are gone. I know the item IS being removed from the cart but not from the table unless I refresh or re-initialize the component. I added a div at the end with an *ngFor loop and when I click the delete button on the table row, the div displays the correct number of items but the table does not. A have a cart.model.ts, a cart.service.ts that handles the deletion (amongst other actions), and then the cart component. I could work with just css or a css library but I would rather find out how to solve this "problem". Any help would be highly appreciated, thanks in advance!
cart.component.html
<div class="mat-display-3" style="background-color: #d6d6d6;
padding: 20px;
color: #a7181b;
text-align: center;" *ngIf="cart.length === 0">
Your cart is Empty!
</div>
<table mat-table [dataSource]="cart" class="mat-elevation-z8" *ngIf="cart.length > 0">
<ng-container matColumnDef="product">
<th mat-header-cell *matHeaderCellDef> Product </th>
<td mat-cell *matCellDef="let cartItem"> <img src="{{ cartItem.image }}" alt="{{ cartItem.name }}"> </td>
</ng-container>
<ng-container matColumnDef="description">
<th mat-header-cell *matHeaderCellDef> Description </th>
<td mat-cell *matCellDef="let cartItem">
<p>Name: {{ cartItem.name }}</p>
<p>Type: {{ cartItem.type }}</p>
<p>Size: {{ cartItem.size }}</p>
</td>
</ng-container>
<ng-container matColumnDef="quantity">
<th mat-header-cell *matHeaderCellDef> Quantity </th>
<td mat-cell *matCellDef="let cartItem"> <input type="number" min="1" max="10" value="{{ cartItem.quantity }}" [disabled]="cartItem.type==='original'"> </td>
</ng-container>
<ng-container matColumnDef="price">
<th mat-header-cell *matHeaderCellDef> Price </th>
<td mat-cell *matCellDef="let cartItem">
<h2>${{ cartItem.price }}.00</h2>
</td>
</ng-container>
<ng-container matColumnDef="delete">
<th mat-header-cell *matHeaderCellDef> Delete </th>
<td mat-cell *matCellDef="let cartItem"> <button mat-fab color="warn" (click)=onDeleteProduct(cartItem.inCartProductId)><mat-icon>delete</mat-icon></button> </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<div *ngFor="let x of cart">
<p>{{ x.name }}</p>
</div>
cart.service.ts
private cart: CartItem[] = [
]
addToCart(name: string, type: string, image: string, size: string, quantity: number, price: number){
let inCartProductId = this.cart.length > 0 ? this.cart[this.cart.length-1].inCartProductId+1 : 1;
this.cart.push({inCartProductId: inCartProductId, name: name, type: type, image: image, size: size, quantity: quantity, price: price});
}
getCart(){
return this.cart;
}
deleteFromCart(inCartProductId: number){
const product = this.cart.find(p => {
return p.inCartProductId === inCartProductId;
});
if(product){
this.cart.splice(this.cart.map(p => p.inCartProductId).indexOf(inCartProductId), 1);
}
}
}
cart-item.model.ts
export class CartItem {
constructor(
public inCartProductId: number,
public name: string,
public type: string,
public image: string,
public size: string,
public quantity: number,
public price: number
){}
}
Solution
mat-table will not render when changes are made to datasource(cart). You need to call it for re-rendering.
In your .ts:
@ViewChild(MatTable, {static: false}) table: MatTable<CartItem>;
After you add or delete data from your cart, add this line:
this.table.renderRows();