我正在使用Angular 8,我创建了一个二维数组(元素),然后用2个* ngFor循环动态生成了一个html表。
<table>
<tr *ngFor="let el of elements, let row = index">
<td *ngFor="let e of el, let col = index" [attr.r] = "row" [attr.c] = "col" contenteditable="true" (blur)="changed($event)">{{ e }}</td>
</tr>
</table>
我的表格单元格是可编辑的“ td”元素,我使用自定义属性“ r”和“ c”设置行号和列号。
当我更改二维数组中的单元格更新时,单元格中的值会正确更新。
然后我添加了“(blur)”事件以检测“ td”中的更改。该事件将按预期方式触发,但是在尝试根据更新来更新数组中的值时出现奇怪的行为。
我的changed()函数如下:
changed(event) {
console.log(event);
let td = (event['target']) as HTMLTableDataCellElement;
console.log(td);
const row = td.getAttribute('r');
const col = td.getAttribute('c');
console.log('r: ' + row);
console.log('c: ' + col);
console.log('value: ' + td.innerHTML);
this.elements[row][col] = td.innerHTML;
console.log('elements[1][1]: ' + this.elements[1][1]);
console.log('elements[1][2] ' + this.elements[1][2]);
console.log('elements[2][1]: ' + this.elements[2][1]);
}
我的桌子如下所示
然后我在单元格“ A1”(即数组的元素1)中输入一个值,然后单击另一个单元格(与哪个单元无关)以触发“ onBlur()”事件
在由事件触发的函数中,我将输入的值写回数组。后台的数组获取正确的值,但是我输入的值被复制到右侧的下一个单元格中。
我在“ changed()”中添加了几个console.log,我得到了一些很奇怪的值。
当我打印“ td”时,它显示c =“ 2”,但是当我查询下一行的属性时,我得到c =“ 1”。 后端中的数组似乎已正确更新为[1] [1] = 1和[1] [2] = 0
我注意到该问题仅在第一次更改单元格时发生。如果我更改A1,则B1将具有相同的值。但是,如果我再次更改A1,该问题将不再发生。
我在这次堆叠闪电战中重现了这个问题:
https://stackblitz.com/edit/angular-ta82dv
我也尝试使用“ focusout”事件,但是我得到了相同的行为。如果有更好/更简便的方法来实现双向数据绑定,请不要犹豫,将我指向另一个方向。
答案 0 :(得分:1)
我想这只是Angular变化检测机制,无法区分所有绑定。因此,您需要提供trackBy
函数:
<table>
<tr *ngFor="let el of elements, let row = index">
<td *ngFor="let e of el, let col = index; trackBy: trackByIndex(row, col)" [attr.r] = "row" [attr.c] = "col" contenteditable="true" (blur)="changed($event)">{{ e }}</td>
</tr>
</table>
函数:
export class AppComponent {
trackByIndex(row, col) {
return () => `${row}:${col}`
}
}
以下是工作示例的链接:https://stackblitz.com/edit/angular-maggnl