5
votes

I am trying to implement a simple table in angular 2 using angular material selection table .

I used a button to remove the selected rows from the table.But on click of the button how can i delete the rows ?

Below shown is my html file for the table

<div class="example-container mat-elevation-z8">
  <mat-table #table [dataSource]="dataSource">

    <!-- Checkbox Column -->
    <ng-container matColumnDef="select">
      <mat-header-cell  style="max-width: 100px;" *matHeaderCellDef>
        <mat-checkbox (change)="$event ? masterToggle() : null"
                      [checked]="selection.hasValue() && isAllSelected()"
                      [indeterminate]="selection.hasValue() && !isAllSelected()">
        </mat-checkbox>
      </mat-header-cell>
      <mat-cell   style="max-width: 100px;" *matCellDef="let row">
        <mat-checkbox (click)="$event.stopPropagation()"
                      (change)="$event ? selection.toggle(row) : null"
                      [checked]="selection.isSelected(row)">
        </mat-checkbox>
      </mat-cell>
    </ng-container>

    <!-- Number Column -->
    <ng-container matColumnDef="num">
      <mat-header-cell style="max-width: 100px;" *matHeaderCellDef> No. </mat-header-cell>
      <mat-cell style="max-width: 100px;" *matCellDef="let element"> {{element.num}} </mat-cell>
    </ng-container>

    <!-- Message Column -->
    <ng-container matColumnDef="name">
      <mat-header-cell *matHeaderCellDef> Message </mat-header-cell>
      <mat-cell *matCellDef="let element"> {{element.name}} </mat-cell>
    </ng-container>


    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumns;"
             (click)="selection.toggle(row)">
    </mat-row>
  </mat-table>

   <mat-paginator #paginator
                 [pageSize]="10"
                 [pageSizeOptions]="[5, 10, 20]">
  </mat-paginator>
</div>

<br/>
<button style="background: #3B4990; color:white;" (click)="deleted($event)">Remove Selected Messages</button>

Below shown is my .ts file.

import {Component, ViewChild} from '@angular/core';
import {MatPaginator, MatTableDataSource} from '@angular/material';
import {SelectionModel} from '@angular/cdk/collections';


@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
   styleUrls: ['./home.component.scss']
})


export class HomeComponent {

displayedColumns = ['select', 'num', 'name'];
  dataSource = new MatTableDataSource<Element>(ELEMENT_DATA);



  @ViewChild(MatPaginator) paginator: MatPaginator;

  /**
   * Set the paginator after the view init since this component will
   * be able to query its view for the initialized paginator.
   */
  ngAfterViewInit() {
    this.dataSource.paginator = this.paginator;
  }

  selection = new SelectionModel<Element>(true, []);

  /** Whether the number of selected elements matches the total number of rows. */
  isAllSelected() {
    const numSelected = this.selection.selected.length;
    const numRows = this.dataSource.data.length;
    return numSelected === numRows;
  }

  /** Selects all rows if they are not all selected; otherwise clear selection. */
  masterToggle() {
    this.isAllSelected() ?
        this.selection.clear() :
        this.dataSource.data.forEach(row => this.selection.select(row));
  }

    deleted($event)
{ 
 delete(this.dataSource.data.forEach(row => this.selection.select(row));)
}

}

export interface Element {
  name: string;
  num: number;
}

const ELEMENT_DATA: Element[] = [
  {num: 1, name: 'Message1'},
  {num: 2, name: 'Message2'},
  {num: 3, name: 'Message3'},
  {num: 3, name: 'Message4'},
  {num: 4, name: 'Message5'},
  {num: 5, name: 'Message6'},
];

can anybody please help me how can i remove the selected rows from the table using the button.

4

4 Answers

17
votes

You should be removing the selected items and refresh the datasource as below,

removeSelectedRows() {
    this.selection.selected.forEach(item => {
       let index: number = this.data.findIndex(d => d === item);
       console.log(this.data.findIndex(d => d === item));
       this.data.splice(index,1)
       this.dataSource = new MatTableDataSource<Element>(this.data);
     });
     this.selection = new SelectionModel<Element>(true, []);
  }

LIVE DEMO

3
votes

You can use the renderRows() method from the MatTable API.

This way you don't have to re-instantiate the array on every click.

Check-out the Live Demo

1
votes

Can you try below?

  removeSelectedRows() {
    var oldData = this.dataSource.data;
    var oldData = oldData.filter((item) => !this.selection.selected.includes(item));
    this.dataSource = new MatTableDataSource<Topic>(oldData);
    this.selection.clear()
    this.dataSource.filter = "";
  }
0
votes

Thanks to Aravind as his answer helped me solve the same problem. However, I didn't like that the MatTableDataSouce was in the forEach loop as I assumed that meant that it was creating a new datasource on each loop. Also, for me, creating a new MatTableDataSource breaks my use of the default Paginator. So I modified his answer and am posting here for anyone that may benefit.

removeSelectedRows() {   
    //sort the selected rows first so that they are in descending order
    //this allows us to splice without the index getting confused
    let selectedRows = this.selection.selected.sort((a,b) => {return b.position - a.position});

    let ds = this.dataSource.data; //take a copy

    selectedRows.forEach(item => {
        ds.splice(item.position-1,1); //splice out the selected rows
    });
    this.dataSource.data = ds;  //set the datasource so it fires the refresh

    this.selection = new SelectionModel<Element>(true, []);
}

Haven't tested it yet but my guess is that some clean up will be required in both the accepted answer and mine as the positions will be out of synch which could mean subsequent calls fail.