如何绑定动态表格内的文本输入框并实现取消回显功能?
问题描述
我有一个带文本输入列的表格,用户编辑文本时,保存和取消按钮会启用。保存按钮能把新值发送到服务器,这部分已经实现,但取消按钮无法将输入框恢复为原值——不管用模型还是子元素,都没法确定当前操作的是表格里的哪一行。
原始模板代码
<table mat-table [dataSource]="gsServersDataSource" class="mat-elevation-z8"> <tr mat-header-row *matHeaderRowDef="gsServersHeaders"></tr> <tr mat-row *matRowDef="let row; columns: gsServersHeaders;"></tr> <ng-container matColumnDef="name"> <th mat-header-cell *matHeaderCellDef > Name </th> <td mat-cell *matCellDef="let element" > {{element.name}} </td> </ng-container> <ng-container matColumnDef="value"> <th mat-header-cell *matHeaderCellDef mat-sort-header sortActionDescription="Sort by value"> Value </th> <td mat-cell *matCellDef="let element"> <input id="valueInput" type="text" value="{{element.value}}" (keyup)="onChangeValue()"> </td> </ng-container> <ng-container matColumnDef="modify"> <th mat-header-cell *matHeaderCellDef> Modify </th> <td mat-cell *matCellDef="let element"> <button id="saveChanges" mat-mini-fab color="primary" (click)="onClickSave()" [disabled]="disabled"> <mat-icon>✓</mat-icon> </button> <button id="cancelChanges" mat-mini-fab color="primary" (click)="onClickCancel(element)" [disabled]="disabled"> <mat-icon>X</mat-icon> </button> </td> </ng-container> </table>
原始组件代码
gsServersDataSource = [{name: 'name1', value: 'value1'}]; gsServersHeaders: string[] = ['name', 'value', 'modify']; disabled=true; onChangeValue(){ this.disabled=false; } onClickSave(element: InstanceDataPoint){ //service call with new value this.disabled=true; } onClickCancel(element: InstanceDataPoint){ //Put original back : How to?? this.disabled=true; }
解决方案
核心是给每行数据保存原始值,同时通过双向绑定让输入框和数据联动,这样取消时直接把原始值赋值回去即可。
1. 扩展数据源,保存原始值
初始化数据源时,给每个对象添加originalValue字段,存储初始的value值:
gsServersDataSource = [{name: 'name1', value: 'value1', originalValue: 'value1'}];
2. 给输入框添加双向绑定
把模板里的静态value替换成Angular的双向绑定[(ngModel)],同时移除重复的id(表格中重复id会导致DOM操作混乱):
<ng-container matColumnDef="value"> <th mat-header-cell *matHeaderCellDef mat-sort-header sortActionDescription="Sort by value"> Value </th> <td mat-cell *matCellDef="let element"> <input type="text" [(ngModel)]="element.value" (keyup)="onChangeValue(element)"> </td> </ng-container>
3. 修复按钮事件,传递当前行元素
给保存按钮也添加当前行元素的传递,同时移除重复的id:
<ng-container matColumnDef="modify"> <th mat-header-cell *matHeaderCellDef> Modify </th> <td mat-cell *matCellDef="let element"> <button mat-mini-fab color="primary" (click)="onClickSave(element)" [disabled]="disabled"> <mat-icon>✓</mat-icon> </button> <button mat-mini-fab color="primary" (click)="onClickCancel(element)" [disabled]="disabled"> <mat-icon>X</mat-icon> </button> </td> </ng-container>
4. 完善组件方法逻辑
disabled=true; onChangeValue(element: any){ this.disabled=false; } onClickSave(element: any){ // 调用服务发送新值到服务器 // 服务调用成功后,更新原始值 element.originalValue = element.value; this.disabled=true; } onClickCancel(element: any){ // 恢复为原始值 element.value = element.originalValue; this.disabled=true; }
可选优化:每行独立控制按钮状态
如果不想用全局的disabled,可以给每个元素添加isDisabled字段,让只有正在编辑的行按钮启用:
// 初始化数据源 gsServersDataSource = [{name: 'name1', value: 'value1', originalValue: 'value1', isDisabled: true}]; // 修改方法 onChangeValue(element: any){ element.isDisabled = false; } onClickSave(element: any){ element.originalValue = element.value; element.isDisabled = true; } onClickCancel(element: any){ element.value = element.originalValue; element.isDisabled = true; }
模板中按钮的[disabled]改为:
<button mat-mini-fab color="primary" (click)="onClickSave(element)" [disabled]="element.isDisabled">
内容的提问来源于stack exchange,提问作者Antonio Craveiro
相关产品推荐
相关产品推荐

