Angular - Drag data

本文透過DragEvent與Angular MVVM的特性,實現表格資料拖動以變更資料排序。

  1. 設定資料列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>
  1. 在拖動開始時,紀錄目標移動資料targetData與其索引targetIndex
targetData: undefined;
targetIndex: number = -1;
dragstart(data: any, rowIndex: number) {
    this.targetData = data;
    this.targetIndex = rowIndex;
}
  1. 拖動進行時,取得進入的資料enterData與其索引enterIndex交換目標資料targetData與進入資料,並比較targetIndexenterIndex的大小,判段目標移動方向。
  • 往下拖動:targetIndex < enterIndex。每當目標往下移動,將前一項資料enterIndex-1替換成進入資料enterData;進入資料enterIndex替換成目標資料targetData。最後紀錄目標資料位置targetIndexenterIndex
  • 往上拖動:targetIndex > enterIndex。每當目標往上移動,將後一項資料enterIndex+1替換成進入資料enterData;進入資料enterIndex替換成目標資料targetData。最後紀錄目標資料位置targetIndexenterIndex
/* 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;
  }
}
  1. 隱藏目標移動資料。
tr.drag-enter {
    opacity: 0;
}

[ngClass]="{'drag-enter' : targetIndex == i}"
  1. 當拖動結束時,顯示該資料。
dragend() { this.targetIndex = -1; }