Atul Stha
Atul Stha

Reputation: 1524

How to splice data in Angular 5 mat-table?

I have used mat-table in my Angular 5 project. The table consists of various data and option of delete. When data gets deleted, it doesn't disappear from the table unless the page is reloaded. I had used splice in another data table used from a package and it worked fine, but in mat-table the same could not be done.

My table's view:

<h5>User List </h5>
<div class="example-container mat-elevation-z8">
    <div class="example-header">
        <mat-form-field>
            <input matInput (keyup)="applyFilter($event.target.value)" matInput placeholder="Filter">
        </mat-form-field>
    </div>

    <mat-table #table [dataSource]="dataSource" matSort>

        <ng-container matColumnDef="id">
            <mat-header-cell *matHeaderCellDef mat-sort-header> User ID</mat-header-cell>
            <mat-cell *matCellDef="let item">
                {{item.id}}
                <span (click)="editUserData(item)"> edit </span>
                <span (click)="viewUserData(item)"> view </span>
                <span (click)="confirmDelete(item)"> delete </span>
            </mat-cell>
        </ng-container>

        <ng-container matColumnDef="name">
            <mat-header-cell *matHeaderCellDef mat-sort-header> Name</mat-header-cell>
            <mat-cell *matCellDef="let item"> {{item.full_name}}</mat-cell>
        </ng-container>

        <ng-container matColumnDef="phone">
            <mat-header-cell *matHeaderCellDef mat-sort-header> Mobile / Phone</mat-header-cell>
            <mat-cell *matCellDef="let item"> {{item.mobile}}</mat-cell>
        </ng-container>

        <ng-container matColumnDef="email">
            <mat-header-cell *matHeaderCellDef mat-sort-header> Email</mat-header-cell>
            <mat-cell *matCellDef="let item"> {{item.email}}</mat-cell>
        </ng-container>

        <ng-container matColumnDef="organization">
            <mat-header-cell *matHeaderCellDef mat-sort-header> Organization</mat-header-cell>
            <mat-cell *matCellDef="let item"> {{item.organization}}</mat-cell>
        </ng-container>

        <ng-container matColumnDef="status">
            <mat-header-cell *matHeaderCellDef mat-sort-header> status</mat-header-cell>
            <mat-cell *matCellDef="let item"> {{item.status}}</mat-cell>
        </ng-container>

        <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
        <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
    </mat-table>
    <mat-paginator #paginator
                   [pageSize]="10"
                   [pageSizeOptions]="[5, 10, 20]"
                   [showFirstLastButtons]="true">
    </mat-paginator>
</div>
<p-confirmDialog header="Confirmation" icon="fa fa-question-circle" width="425"></p-confirmDialog>

My component's ngOnit portion where I have set the datasource:

ngOnInit()
{

    this.appService.getUserDataList().subscribe(res => {
        this.employeeTemp = res;
        console.log('THIS IS AGAIN ME', this.employeeTemp);
        this.dataSource = new MatTableDataSource(this.employeeTemp);
        this.dataSource.paginator = this.paginator;
        this.dataSource.sort = this.sort;

    });

}

My confirmDelete function:

confirmDelete(item)
{
    this.confirmationService.confirm({
        message: 'Are you sure you want to delete this Employee?',
        header: 'Confirmation',
        accept: () => {
            this.appService.deleteUser(item.id).subscribe(res => {
                    // Splice Or something so the page doesnt reload but the data gets removed from the view.
                    const index = this.dataSource.indexOf(item);
                    this.dataSource.splice(index, 1);
                    this.flashMsg.flashMsg('success', 'Deleted', 'User has been deleted.'); //  this.EmployeeListComponent();
                },
                err => {
                    this.flashMsg.flashMsg('error', 'Error', 'User has not been deleted.');
                });
        },
        reject: () => {
        },
    });
}

The value stored in item of confirmDelete function:

address :" "
email:"[email protected]"
full_name:"asdf asdf"
id:"[email protected]"
mobile:"12345678"
organization:"VURUNG TECH"
status:"Active"
updated_at:"2018-06-20T05:15:52.000Z

I get the success flashMessage displayed but the splice doesnot work.

Upvotes: 2

Views: 5230

Answers (4)

Mohsin Ejaz
Mohsin Ejaz

Reputation: 414

Please reproduce these steps exactly.

-> Step#1

dataSource: any = new MatTableDataSource()

-> Step#2 Splice at index

this.dataSource.data.splice(currentIndex, 1);

-> Step#3 then to update view

 this.dataSource._data.next(this.dataSource.data)

Very important: In order to avoid this error

"Property '_data' is private and only accessible within class 'MatTableDataSource"

Don't forget any with dataSource:

step#1 'dataSource : any'   

-> Detail of step #2 (information only)

When I console, I see there behaviour '_data' subject property of dataSource. So I update it, so that the view shall update. when i console i see there behaviour ('_data') subject property of dataSouce. So i update it so that view shall update

Upvotes: 0

Antoniossss
Antoniossss

Reputation: 32535

Try to invoke change detection run after model changes.

constructor(private cdr:ChangeDetectionRef)

and

this.appService.deleteUser(item.id).subscribe(res => {
         ....
         this.cdr.detectChanges();
        ....
      },

Upvotes: 0

Anshuman Jaiswal
Anshuman Jaiswal

Reputation: 5462

Try by resetting datasource or updating data of datasource as:

confirmDelete(item) {
    this.confirmationService.confirm({
      ...
      accept: () => {
        this.appService.deleteUser(item.id).subscribe(res => {
            this.employeeTemp = this.employeeTemp.filter(employee => employee.id != item.id)
            this.dataSource = new MatTableDataSource(this.employeeTemp);
            //this.dataSource.data = this.employeeTemp; <=== You can also change only data
            ...
          },
          ...
      }
      ...
    });
}

Upvotes: 3

Carsten
Carsten

Reputation: 4208

Make a reference to <mat-table> using the hashtag: <mat-table #table [dataSource]="dataSource">.

Get the reference inside the component ts:

@ViewChild('table') table: MatTable<any>;

after this.dataSource.splice(index, 1); call:

this.table.renderRows();

Upvotes: 1

Related Questions