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

Angular双拖拽列表加筛选后transferArrayItem索引错误移错项问题

Angular拖拽列表筛选后索引错位修复方案

根本原因:视图层渲染的是筛选后的子集数组,transferArrayItem方法默认传入的是筛选后列表的索引,和原始数组的索引无法对应,导致移动的条目和选中条目不一致。

修复步骤

  • 拆分数据源,分别维护「原始数据数组」和「筛选后展示数组」,不要直接修改原始数组用于筛选渲染;给所有列表项设置唯一id属性,放弃依赖索引定位条目。
  • 绑定cdkDragStarted事件,拖拽开始时直接记录当前拖拽项的唯一id,而非依赖事件返回的索引:
    模板代码示例:
    <div cdkDrag *ngFor="let item of filteredList1" (cdkDragStarted)="recordDragItem(item.id, 1)">
      {{ item.name }}
    </div>
    
    对应逻辑代码:
    // 存储当前拖拽的条目实例
    currentDragItem: any;
    
    recordDragItem(id: number, listNo: 1 | 2) {
      const sourceList = listNo === 1 ? this.originList1 : this.originList2;
      this.currentDragItem = sourceList.find(i => i.id === id);
    }
    
  • 重写drop事件逻辑,移动条目时先查找到拖拽项在原始数组的真实索引,再调用transferArrayItem:
    drop(event: CdkDragDrop<any[]>) {
      if (event.previousContainer === event.container) {
        moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
        // 同列表排序后重新触发筛选刷新视图
        this.refreshFilterList();
        return;
      }
      // 查找拖拽项在原始源列表的真实索引
      const sourceOriginList = event.previousContainer.data;
      const realPrevIndex = sourceOriginList.findIndex(i => i.id === this.currentDragItem.id);
      // 用真实索引执行移动
      transferArrayItem(sourceOriginList, event.container.data, realPrevIndex, event.currentIndex);
      // 移动完成后刷新两个列表的筛选结果
      this.refreshFilterList();
    }
    
  • 单独封装refreshFilterList方法,每次输入搜索关键词、完成拖拽操作后触发,基于最新的原始数组生成筛选后的展示数组。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 17:06:09