You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular表格编辑异常:取消编辑后数据仍被修改

问题解决:PrimeNG表格行编辑取消后数据仍被修改的问题

问题分析

你的问题根源确实是双向绑定直接修改了原始数据对象:

  • 编辑框输入内容时,[(ngModel)]="data.value"会实时修改原数组中的data对象,哪怕未点击保存或取消
  • 取消编辑时,你尝试用editedData备份替换原数据,但数组是引用类型,加上定时更新逻辑会保留已修改的对象,导致10秒后数据更新时修改依然存在
  • 之前的浅拷贝[...tableData]仅复制数组引用,内部对象还是原引用,无法解决问题

修复方案

1. 调整表格组件的编辑逻辑,使用独立临时编辑对象

编辑初始化时创建原数据的深拷贝(切断引用关联),编辑时绑定这个临时对象,取消时直接丢弃,保存时再更新原数据:

export class TableComponent {
  @Input() tableData: IData[] = [];
  // 存储临时编辑对象,key为数据id
  editedData: { [s: string]: IData } = {};

  constructor(private dataService: DataService) {}

  onRowEditInit(data: IData) {
    // 深拷贝原数据,避免引用关联
    this.editedData[data.id] = JSON.parse(JSON.stringify(data));
  }

  editRow(data: IData, rowIndex: number) {
    // 保存时用临时对象替换原数组中的对象
    this.tableData[rowIndex] = { ...this.editedData[data.id] };
    this.dataService.setData([...this.tableData]);
    delete this.editedData[data.id];
  }

  onRowEditCancel(data: IData) {
    // 取消时直接删除临时对象,原数据未被改动无需回写
    delete this.editedData[data.id];
  }
}

2. 修改HTML模板,绑定临时编辑对象而非原数据

在p-cellEditor的输入模板中,绑定editedData[data.id]的属性,避免直接修改原数据:

<div class="container">
  <p-table
    [value]="tableData"
    dataKey="id"
    editMode="row"
    scrollHeight="flex"
    styleClass="p-datatable-gridlines"
    [rows]="8"
    [scrollable]="true"
  >
    <ng-template pTemplate="header">
      <tr>
        <th class="time">Time</th>
        <th class="value">Value</th>
        <th class="action"></th>
      </tr>
    </ng-template>
    <ng-template
      pTemplate="body"
      let-data
      let-editing="editing"
      let-ri="rowIndex"
    >
      <tr [pEditableRow]="data">
        <td class="p-column-title">
          <p-cellEditor>
            <ng-template pTemplate="input">
              <input 
                pInputText 
                type="text" 
                [(ngModel)]="editedData[data.id].time" 
              />
            </ng-template>
            <ng-template pTemplate="output">
              {{ data.time | date : "yyyy-MM-dd HH:mm:ss" }}
            </ng-template>
          </p-cellEditor>
        </td>
        <td>
          <p-cellEditor>
            <ng-template pTemplate="input">
              <input 
                pInputText 
                type="number" 
                [(ngModel)]="editedData[data.id].value" 
              />
            </ng-template>
            <ng-template pTemplate="output">
              {{ data.value | number : "1.2-2" }}
            </ng-template>
          </p-cellEditor>
        </td>
        <td class="action-button">
          <div class="flex align-items-center justify-content-center gap-2">
            <button
              *ngIf="!editing"
              pButton
              pRipple
              type="button"
              (click)="onRowEditInit(data)"
              pInitEditableRow
              icon="pi pi-pencil"
              class="p-button-rounded p-button-text"
            ></button>
            <button
              *ngIf="editing"
              pButton
              pRipple
              (click)="editRow(data, ri)"
              type="button"
              pSaveEditableRow
              icon="pi pi-check"
              class="p-button-rounded p-button-text p-button-success mr-2"
            ></button>
            <button
              *ngIf="editing"
              pButton
              pRipple
              (click)="onRowEditCancel(data)"
              type="button"
              pCancelEditableRow
              icon="pi pi-times"
              class="p-button-rounded p-button-text p-button-danger"
            ></button>
          </div>
        </td>
      </tr>
    </ng-template>
  </p-table>
</div>

3. 优化数据更新逻辑(可选)

在main.component.ts中,更新数据时生成新数组引用,避免变更检测异常:

addNewData() {
  const newData: IData = {
    id: Date.now().toString(),
    time: new Date(),
    value: Math.floor(Math.random() * 1000)
  };
  this.data.push(newData);
  // 过滤最近30分钟的数据
  const thirtyMinutesAgo = new Date(Date.now() - 30 * 60 * 1000);
  this.data = this.data.filter(item => new Date(item.time) >= thirtyMinutesAgo);
  this.dataService.setData([...this.data]);
  this.latestValue = newData.value;
}

关键修复点

  • 编辑时绑定临时深拷贝对象,避免实时修改原数据
  • 取消编辑时直接丢弃临时对象,无需回写原数据
  • 保存时才将临时对象的值同步到原数组,并触发数据服务更新

内容的提问来源于stack exchange,提问作者krk5570

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 03:49:58