[Fixed] How to remove a row from an Angular Material table

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!
enter image description here

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();

Leave a Reply

(*) Required, Your email will not be published