Skip to content Skip to sidebar Skip to footer

How To Implement Edit, Update And Discard Functions In Angular Material Table(mat-table)

I want to implement edit, update and discard functions in angular material table. I know how to edit and update table row wise but do not know how to discard the table rows. please

Solution 1:

You could switch the ngModel of the form fields to a temporary working copy. If the user then discards, you just need to remove the working copy and display the original contents again. If on the other hand the user wants to save, we Object.assign the changes to the table data.

See here: https://stackblitz.com/edit/angular-material-starter-njrnu9?file=app/app.component.ts

This solution is not perfect, but maybe it guides you in the right direction.

Solution 2:

when you edit make a copy of element. Then you has two aproach:

1.- you use [ngModel] with the copy and in update asign the value

2.- you use [ngModel] with the element and in cancel asign the copyvalue

To make a copy you need use the spread operator, to make a "copy", not to asign the same object to the two variables

this.oldValue={...element}

Well. You need choose if you can edit severals rows at time or only one. I think that it's more adecuate edit only one row at time (but it's only an opinion), so first, in stead of has in an array if a row is in edit mode or not you can use an unique variable editIndex

editIndex:number=-1;
  editCompanyDetails(details,i) {
    this.editIndex=i;
  }

I choose edit the "copy", so I declare a variable newValue

newValue:any;
  editCompanyDetails(details,i) {
    this.editIndex=i;
    this.newValue={...details}
  }

See how we make a copy using spread operator

There're a problem that we can not use the same mat-form field in edit mode and in read-only mode. MatTable not allow us make some like:

<!-- this NOT WORK --><inputmatInputplaceholder="{{element.companyName}}"
             [(ngModel)]="editIndex==i?newValue.companyName:element.companyName"...>

So, we need "repeat" the form field, one using element and one using newValue.

<ng-containermatColumnDef="companyName"><mat-header-cell *matHeaderCellDef> Company Name </mat-header-cell><mat-cell *matCellDef="let element;let i = index"><!--this only show is editIndex!=i--><mat-form-field *ngIf="editIndex!=i"floatLabel="never" [appearance]="'none'"><inputmatInputplaceholder="{{element.companyName}}"
 [(ngModel)]="element.companyName"
         [readonly]="true"></mat-form-field><!--this only show is editIndex==i--><mat-form-field *ngIf="editIndex==i"floatLabel="never" [appearance]="'legacy'"><inputmatInputplaceholder="{{element.companyName}}"
 [(ngModel)]="newValue.companyName"
         ></mat-form-field></mat-cell></ng-container><ng-containermatColumnDef="status"><mat-header-cell *matHeaderCellDef> Status </mat-header-cell><mat-cell *matCellDef="let element;let i = index"><!--this only show is editIndex!=i--><mat-form-field *ngIf="editIndex!=i"floatLabel="never" [appearance]="'none'"><inputmatInput [(ngModel)]="element.status" [readonly]="true" ></mat-form-field><!--this only show is editIndex==i--><mat-form-field *ngIf="editIndex==i"floatLabel="never" [appearance]="'legacy'"><inputmatInput [(ngModel)]="newValue.status"  ></mat-form-field></mat-cell></ng-container>

the functions update and cancel becomes like

  updateCompanyDetails(i){
    this.dataSourceCompanyDetails.data[i]={...this.newValue}
    this.editIndex=-1;
  }

  discardCompanyDetails(){
    this.editIndex=-1;
  }

You can see in this forked stackbliz

NOTE: In this aproach, if you're editing one field and try edit another one, the changes are loose. Perhasf is time that, in edit function check if editIndex!=-1 to ask if you want to loose the changes (not in stackblitz)

  editCompanyDetails(details,i) {
    if (this.editIndex!=i && this.editIndex!=-1)
    {
       //get the element we are "editing"constdata=dataSourceCompanyDetails.data[this.editIndex]
       if (data.status!=this.newValue.status || data.companyName!=this.newValue.companyName){
         ..ask if you want to loose the changes..
       }
    }
       if (this.newValue.
    this.editIndex=i;
    this.newValue={...details}
  }

updated y we take the another aproach declare a variable olValue and get the table using ViewChild -is necesary call to renderRows y cancel the edit.

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

And change the functions as

  editCompanyDetails(details,i) {
    this.editIndex=i;
    this.oldValue={...details}
  }

  updateCompanyDetails(){
    this.editIndex=-1;
  }

  discardCompanyDetails(i){
    this.dataSourceCompanyDetails.data[i]={...this.oldValue}
    this.editIndex=-1;
    this.table.renderRows()
  }

Well, change the [NgModel]="newElement.company bt [ngModel="element.company". I'm in hurry, but this aproach you can use an unique formField, in the stackblitz I left the two formFields

See the new stackblitz

Solution 3:

if you wanna implement discard functionality properly we have a way, instead of following 2 way data binding we could follow reactive forms and could create form arrays. below is my solution.table with discard functions

Post a Comment for "How To Implement Edit, Update And Discard Functions In Angular Material Table(mat-table)"