说实话我是不太清楚这篇博客的标题该怎么写
因为这并不是一篇科普或技术文章,而是记录我遇到的问题
但是这个问题的解决方法或者说思路非常有意思,还是打算记录一下XD
这里的某些代码命名会有点儿蠢,因为我是后接手这个页面的,与我无瓜!
初始功能描述
NG-ZORRO的表格,单击单元格可以进入该行的编辑模式,该行单元格均变为Input框。
表格在文档中的位置 Table(表格) | NG-ZORRO
当Input框失去焦点后会重新进入只读模式,并保存已编辑的内容。
由于整篇代码的量比较大,所以接下来均会用编号这一列的代码用作示例。
html代码:
<nz-table #editRowTable nzBordered [nzData]="listOfData" nzTableLayout="fixed" class="NZTable"
[nzShowPagination]="false" [nzFrontPagination]="false">
<thead>
<tr>
<th nzWidth="5%">编号</th>
</tr>
</thead>
<tbody>
<td (click)="startEdit(data.position)">{{ data.id15 }}</td>
</ng-container>
<ng-template #editTemplate>
<td><input type="text" nz-input [(ngModel)]="editCache[data.position].data.id15" (blur)="saveEdit(data.position)" /></td>
</ng-template>
</tr>
</tbody>
</nz-table>
ts代码:
// 面料表格所用编辑函数
startEdit(id: string): void {
this.listOfData.forEach(index => {
if (index['position'] == id) {
this.editCache[index['position']].edit = true;
} else {
this.editCache[index['position']].edit = false;
}
})
}
saveEdit(id: string | number): void {
const index = this.listOfData.findIndex(item => item.position === id);
Object.assign(this.listOfData[index], this.editCache[id].data);
this.listOfData = [...this.listOfData];
this.editCache[id].edit = false;
this.isEdit = true;
}
产品需求
由于编辑模式和只读模式是基于单元格的函数进行的,也就是说我进入A单元格的编辑模式后,是该行全部进入编辑模式,当我点击B单元格的input框时,由于触发了失去焦点函数,直接退出了编辑模式,很不方便。
产品希望在某行进入编辑模式的时候,该行的input框可以随意点击不会退出。
解决思路
需要知道的是,【失去焦点-保存数据】这个行为仅仅是在编辑模式和只读模式之间切换的时候自动触发的,模拟Excel那种保存的方式(这里指的是展现的数据保存,而不是文件的保存)
那么我们就可以放弃【失去焦点】才会【保存数据】,而将【保存数据】这个行为自行控制。
在单行数据随意编辑的情况下,什么时候才会触发【保存数据】这个行为呢,那就是跨行编辑的时候,从第x行切换到第y行的时候,我们就知道用户完成了这一行的编辑,触发保存即可。
所以我定义了一个字段positionIndex,用于存储用户当前的所在行,当进入编辑模式回传的position与positionIndex不相同时,就代表用户跨行编辑了。
具体实现
html代码:
<nz-table #editRowTable nzBordered [nzData]="listOfData" nzTableLayout="fixed" class="NZTable"
[nzShowPagination]="false" [nzFrontPagination]="false">
<thead>
<tr (click)="updateEditCache()">
<th nzWidth="5%">编号</th>
</tr>
</thead>
<tbody>
<td (click)="startEdit(data.position)">{{ data.id15 }}</td>
</ng-container>
<ng-template #editTemplate>
<td><input type="text" nz-input [(ngModel)]="editCache[data.position].data.id15" /></td>
</ng-template>
</tr>
</tbody>
</nz-table>
html代码其实没有什么变动,只在表头添加了一个click函数pdateEditCache(),可以通过点击表头退出编辑模式触发保存。
ts代码:
// 判断鼠标目前在第几行
positionIndex = 100;
// 面料表格所用编辑函数
startEdit(id: string): void {
// 只有存的索引不等于id时,意味着跨行进入了编辑模式,则保存上一行的数据
if (Number(id) !== this.positionIndex && this.positionIndex !== 100) {
this.saveEdit(this.positionIndex);
}
// 当进入编辑模式时赋值positionIndex,代表当前用户所在的行数
this.positionIndex = Number(id);
// 进入编辑模式
this.listOfData.forEach(index => {
if (index['position'] == id) {
this.editCache[index['position']].edit = true;
} else {
this.editCache[index['position']].edit = false;
}
})
}
// 退出编辑模式,且对数据进行保存
saveEdit(id: string | number): void {
const index = this.listOfData.findIndex(item => item.position === id);
Object.assign(this.listOfData[index], this.editCache[id].data);
this.listOfData = [...this.listOfData];
this.editCache[id].edit = false;
this.isEdit = true;
}
这一块代码其实并不多,看起来也非常简单,是因为这是我最后已经解决的成果代码。
最开始的时候我是陷入了一个很大的误区,虽然我刚开始的时候就使用了positionIndex这个字段,但我一直在html中使用焦点去触发【退出编辑模式并保存】。
我其实是将【点击-失焦-触发】的流程定死了,并没有想到【触发】可以不使用【失焦】的方式,可以在代码中自己掌控。