You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于ng2-dragula的Angular5多选中拖拽排序功能实现需求

实现ng2-dragula多选拖拽排序功能

我来帮你搞定这个按住Ctrl多选后拖拽排序的需求!核心思路是利用Dragula提供的事件钩子,拦截默认的单元素拖拽行为,手动处理选中项的数组移除和插入逻辑。

步骤1:订阅Dragula的关键事件

首先我们需要在组件中订阅Dragula的drop事件(拖拽完成时触发),同时为了避免内存泄漏,要在组件销毁时取消订阅。另外,为了阻止默认的单元素拖拽干扰多选操作,我们还可以订阅drag事件,当有多个选中项时阻止默认拖拽行为。

步骤2:实现多选拖拽的核心逻辑

当拖拽完成时,我们需要:

  • 判断是否有多个选中项
  • 获取拖拽目标位置的索引
  • 把选中项从原数组中移除(注意要按索引从大到小删除,避免索引偏移问题)
  • 将选中项插入到目标位置
  • 清空选中数组,恢复初始状态

修改后的完整代码

app.component.html(无需修改,保持原结构即可)

<table border=2>
 <tbody id='dest' [dragula]='"second-bag"' [dragulaModel]="peoples">
 <tr *ngFor="let person of peoples" (click)="addThisPersonToArray(person, $event)" [class.active]="isPersonSelected(person)">
 <td>{{person.id}}</td>
 <td>{{person.firstName}}</td>
 <td>{{person.lastName}}</td>
 </tr>
 </tbody>
</table>
Result items
<ul>
 <li *ngFor="let item of peoples"> {{item.firstName}}</li>
</ul>

app.component.ts(添加事件订阅和核心逻辑)

import { Component, OnInit, OnDestroy } from '@angular/core';
import { DragulaService } from 'ng2-dragula/ng2-dragula';
import { Subscription } from 'rxjs';

@Component({
 selector: 'app-root',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, OnDestroy {
 selectedPersonArray = [];
 peoples = [
 { id: 1, firstName: 'First Name 1', lastName: 'Last Name 1' },
 { id: 2, firstName: 'First Name 2', lastName: 'Last Name 2' },
 { id: 3, firstName: 'First Name 3', lastName: 'Last Name 3' },
 { id: 4, firstName: 'First Name 4', lastName: 'Last Name 4' },
 { id: 5, firstName: 'First Name 5', lastName: 'Last Name 5' },
 { id: 6, firstName: 'First Name 6', lastName: 'Last Name 6' }
 ];

 private dragSub: Subscription;
 private dropSub: Subscription;

 constructor(private dragulaService: DragulaService) {
   // 初始化Dragula的bag,确保支持拖拽
   this.dragulaService.createGroup('second-bag', {
     moves: (el, container, handle) => true,
     direction: 'vertical'
   });
 }

 ngOnInit() {
   // 订阅drag事件,当有多个选中项时阻止默认拖拽
   this.dragSub = this.dragulaService.drag('second-bag').subscribe(({ el }) => {
     if (this.selectedPersonArray.length > 1) {
       // 阻止默认的单元素拖拽行为
       el.setAttribute('draggable', 'false');
     }
   });

   // 订阅drop事件,处理多选拖拽逻辑
   this.dropSub = this.dragulaService.drop('second-bag').subscribe(({ target, source }) => {
     if (this.selectedPersonArray.length <= 1) return;

     // 获取目标位置的索引
     const targetIndex = Array.from(target.children).indexOf(target.querySelector('.active') || target.firstElementChild);
     // 复制选中项的副本,避免原数组修改影响
     const selectedItems = [...this.selectedPersonArray];

     // 按索引从大到小删除选中项,防止索引偏移
     selectedItems.sort((a, b) => {
       const idxA = this.peoples.indexOf(a);
       const idxB = this.peoples.indexOf(b);
       return idxB - idxA;
     }).forEach(item => {
       const idx = this.peoples.indexOf(item);
       if (idx !== -1) {
         this.peoples.splice(idx, 1);
       }
     });

     // 将选中项插入到目标位置
     this.peoples.splice(targetIndex, 0, ...selectedItems);

     // 清空选中数组
     this.selectedPersonArray = [];
   });
 }

 toggleItemInArr(arr, item) {
   const index = arr.indexOf(item);
   index === -1 ? arr.push(item) : arr.splice(index, 1);
 }

 addThisPersonToArray(person: any, event) {
   if (!event.ctrlKey) {
     this.selectedPersonArray = [];
   }
   this.toggleItemInArr(this.selectedPersonArray, person);
 }

 isPersonSelected(person: any) {
   return (this.selectedPersonArray.indexOf(person) !== -1);
 }

 ngOnDestroy() {
   // 取消订阅,防止内存泄漏
   this.dragSub?.unsubscribe();
   this.dropSub?.unsubscribe();
   // 销毁Dragula的bag
   this.dragulaService.destroy('second-bag');
 }
}

关键代码解释

  • Dragula Group初始化:我们显式创建了second-bag组,确保拖拽方向为垂直方向,符合表格行的拖拽场景。
  • drag事件处理:当有多个选中项时,设置拖拽元素为不可拖拽,避免默认的单元素拖拽逻辑干扰。
  • drop事件处理:
    • 获取目标位置的索引:通过遍历目标容器的子元素找到拖拽目标的位置。
    • 反向删除选中项:按原数组中的索引从大到小删除,这样删除前面的元素不会影响后面元素的索引。
    • 插入选中项:使用spread操作符将选中项批量插入到目标位置。
  • 组件销毁清理:取消事件订阅并销毁Dragula组,避免内存泄漏。

测试场景验证

现在你可以按住Ctrl键选中2和4,然后拖拽到1的位置,列表会变成2,4,1,3,5,6,完全符合你的需求!

内容的提问来源于stack exchange,提问作者Rosa Mystica

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:51:25