Angular - Drag data
本文透過DragEvent與Angular MVVM的特性,實現表格資料拖動以變更資料排序。
- 設定資料列
tr
可拖動draggable="true"
。
<tr *ngFor="let data of dataSet; let i = index;"
[ngClass]="{'drag-enter' : targetIndex == i}"
draggable="true"
(dragstart)="dragstart(data,i)"
(dragenter)="dragenter(data,i)"
(dragend)="dragend()">
<td *ngFor="let field of dataField">
{{ data[field.value] }}
</td>
</tr>
- 在拖動開始時,紀錄目標移動資料
targetData
與其索引targetIndex
。
targetData: undefined;
targetIndex: number = -1;
dragstart(data: any, rowIndex: number) {
this.targetData = data;
this.targetIndex = rowIndex;
}
- 拖動進行時,取得進入的資料
enterData
與其索引enterIndex
交換目標資料targetData
與進入資料,並比較targetIndex
與enterIndex
的大小,判段目標移動方向。
- 往下拖動:
targetIndex < enterIndex
。每當目標往下移動,將前一項資料enterIndex-1
替換成進入資料enterData
;進入資料enterIndex
替換成目標資料targetData
。最後紀錄目標資料位置targetIndex
為enterIndex
。 - 往上拖動:
targetIndex > enterIndex
。每當目標往上移動,將後一項資料enterIndex+1
替換成進入資料enterData
;進入資料enterIndex
替換成目標資料targetData
。最後紀錄目標資料位置targetIndex
為enterIndex
。
/* switch enterData and targetData */
dragenter(enterData: any, enterIndex: number) {
if(enterIndex > this.targetIndex) { // drag direction: ↓
this.dataSet[enterIndex-1] = enterData;
this.dataSet[enterIndex] = this.targetData;
this.targetIndex = enterIndex;
}
else if(enterIndex < this.targetIndex) { // drag direction: ↑
this.dataSet[enterIndex+1] = enterData;
this.dataSet[enterIndex] = this.targetData;
this.targetIndex = enterIndex;
}
}
- 隱藏目標移動資料。
tr.drag-enter {
opacity: 0;
}
[ngClass]="{'drag-enter' : targetIndex == i}"
- 當拖動結束時,顯示該資料。
dragend() { this.targetIndex = -1; }