简体   繁体   English

如何在角度材料表(mat-table)中实现编辑、更新和丢弃功能

[英]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 click on link stackblitz link to table to see what i have done.请点击链接stackblitz 链接到表格,看看我做了什么。 if you know how to implement discard functions please help me, and any help would be appreciated, i do not how to keep the initial values of data cells.如果您知道如何实现丢弃功能,请帮助我,任何帮助将不胜感激,我不知道如何保留数据单元格的初始值。 even i tried to keep a copy of the original data so that when they hit on discard button i can move copied data to particular row of the table.即使我试图保留原始数据的副本,以便当他们点击丢弃按钮时,我可以将复制的数据移动到表的特定行。 but because of 2 way data binding its directly updating to original data(i mean to company details array which is response from backend), i do not know how its reflecting and effecting original data.但是由于 2 路数据绑定它直接更新到原始数据(我的意思是公司详细信息数组,它是后端的响应),我不知道它如何反映和影响原始数据。 its a kinda weird thing i am facing here, please help me badly i need this answer thx in advance.这是我在这里面临的一件奇怪的事情,请帮助我,我需要提前得到这个答案。

You could switch the ngModel of the form fields to a temporary working copy.您可以将表单字段的 ngModel 切换到临时工作副本。 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.另一方面,如果用户想要保存,我们 Object.assign 对表数据的更改。

See here: https://stackblitz.com/edit/angular-material-starter-njrnu9?file=app/app.component.ts请参阅此处: 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.这个解决方案并不完美,但也许它可以引导您朝着正确的方向前进。

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 1.- 您将 [ngModel] 与副本一起使用,并在更新中分配值

2.- you use [ngModel] with the element and in cancel asign the copyvalue 2.-您将 [ngModel] 与元素一起使用并取消分配复制值

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

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

I choose edit the "copy", so I declare a variable newValue我选择编辑“复制”,所以我声明了一个变量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.有一个问题,我们不能在编辑模式和只读模式下使用相同的 mat-form 字段。 MatTable not allow us make some like: MatTable 不允许我们做一些像:

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

So, we need "repeat" the form field, one using element and one using newValue.因此,我们需要“重复”表单字段,一个使用元素,一个使用 newValue。

      <ng-container matColumnDef="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'">
            <input matInput placeholder="{{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'">
            <input matInput placeholder="{{element.companyName}}"
 [(ngModel)]="newValue.companyName"
         >
          </mat-form-field>
        </mat-cell>
      </ng-container>

      <ng-container matColumnDef="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'">
            <input matInput [(ngModel)]="element.status" [readonly]="true" >
          </mat-form-field>

          <!--this only show is editIndex==i-->
          <mat-form-field *ngIf="editIndex==i" floatLabel="never" [appearance]="'legacy'">
            <input matInput [(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你可以在这个分叉的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) Perhasf 是时候了,在编辑函数中检查是否 editIndex!=-1 询问您是否要取消更改(而不是在 stackblitz 中)

  editCompanyDetails(details,i) {
    if (this.editIndex!=i && this.editIndex!=-1)
    {
       //get the element we are "editing"
       const data=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.更新y 我们采取另一种方法声明一个变量 olValue 并使用 ViewChild 获取表 - 是对 renderRows 的必要调用 y 取消编辑。

@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好吧,更改 [NgModel]="newElement.company bt [ngModel="element.company"。我很着急,但是这种方法可以使用唯一的 formField,在 stackblitz 中我留下了两个 formField

See the new stackblitz查看新的堆栈闪电战

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.如果您想正确实现丢弃功能,我们有一种方法,而不是遵循 2 路数据绑定,我们可以遵循反应式表单并可以创建表单数组。 below is my solution.下面是我的解决方案。 table with discard functions 带丢弃函数的表

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM