6

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.

0

4 Answers 4

18

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

Sign up to request clarification or add additional context in comments.

7 Comments

is it not possible instead of deleting them all to only remove a portion according to selection?
@Aravind Thank you for the LiveDemo, though when taking a look when I click on Remove buttons I can still see the row it is not removed. Is it normal ? I'm using google chrome
and in your example if the previous dataSource had some paginator and sort aren't you losing them? like @ViewChild('myPaginator') myPaginator: MatPaginator; in onInit() -> dataSource.paginator = myPaginator;
@Sithys example works fine now! thanks for notification
great work brother. It worked for me with little modification I was able to do add part too.@Aravind
|
3

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

4 Comments

Is it only Angular 6 method ?
Yep saw it too, but somehow I can not find this method inn MatTable using Angular 5 :(
@LoganWlv It was introduced on V.5.2.x
Your live demo link was helpful but it worked without me having to call renderRows()
1

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 = "";
  }

1 Comment

While this code may solve the question, including an explanation of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please edit your answer to add explanations and give an indication of what limitations and assumptions apply.
0

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.

1 Comment

Subsequent calls do indeed fail... need to add a couple of lines before setting the datasource let i = 1; ds.forEach(item => { item.position = i++; });

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.