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

如何在Angular拖拽中识别源容器与目标容器

解决方案:识别Angular CDK拖拽的源/目标容器并更新任务状态

要准确识别拖拽的源容器、目标容器,并同步更新任务状态,你可以通过以下方式修改代码:

1. 给拖拽容器绑定唯一标识

在task-status.component.html中,给cdkDropList添加状态key作为唯一ID,同时给cdkDrag绑定任务数据:

<div class="task-status-container">
  <div class="title-container">
    <div class="title">{{ taskStatus.value }}</div>
  </div>

  <div
    cdkDropList
    [cdkDropListId]="taskStatus.key" <!-- 绑定状态key为容器ID -->
    [cdkDropListData]="assignTasksByStatus(taskStatus.key)"
    (cdkDropListDropped)="drop($event)"
    class="task-status-container-body"
  >
    @for (task of assignTasksByStatus(taskStatus.key);track task.id) {
    <app-task cdkDrag [task]="task" [cdkDragData]="task"></app-task> <!-- 绑定任务数据到拖拽元素 -->
    }
  </div>
</div>

2. 在drop事件中识别容器并更新任务状态

修改task-status.component.ts中的drop方法,直接通过容器ID获取状态类型,同时拿到被拖拽的任务并更新其状态:

drop(event: CdkDragDrop<Task[]>) {
  const sourceStatus = event.previousContainer.id;
  const targetStatus = event.container.id;
  const draggedTask = event.item.data as Task;

  // 可直接打印源/目标状态用于调试
  console.log(`任务从 ${sourceStatus} 移至 ${targetStatus}`);

  if (event.previousContainer === event.container) {
    moveItemInArray(
      event.container.data,
      event.previousIndex,
      event.currentIndex
    );
  } else {
    transferArrayItem(
      event.previousContainer.data,
      event.container.data,
      event.previousIndex,
      event.currentIndex
    );
    // 更新任务的状态值
    draggedTask.status = this.TASK_STATUSES[targetStatus as keyof typeof TASK_STATUSES];
    // 同步tasksByStatus数据,确保视图与数据一致
    this.tasksByStatus[sourceStatus] = this.tasksByStatus[sourceStatus].filter(t => t.id !== draggedTask.id);
    this.tasksByStatus[targetStatus].push(draggedTask);
  }
}

关键逻辑说明

  • cdkDropListId:将容器与TO_DO/DONE这类状态key绑定,让你能在drop事件中直接获取容器对应的状态类型,无需额外解析。
  • cdkDragData:把任务对象直接绑定到拖拽元素,无需遍历数组查找,直接拿到被拖拽的任务实例更新状态。
  • 数据同步:任务状态变更后,同步更新tasksByStatus,避免视图数据不一致。

修改后的完整代码片段

task-status.component.html

<div class="task-status-container">
  <div class="title-container">
    <div class="title">{{ taskStatus.value }}</div>
  </div>

  <div
    cdkDropList
    [cdkDropListId]="taskStatus.key"
    [cdkDropListData]="assignTasksByStatus(taskStatus.key)"
    (cdkDropListDropped)="drop($event)"
    class="task-status-container-body"
  >
    @for (task of assignTasksByStatus(taskStatus.key);track task.id) {
    <app-task cdkDrag [task]="task" [cdkDragData]="task"></app-task>
    }
  </div>
</div>

task-status.component.ts

export class TaskStatusComponent {
  protected readonly TASK_STATUSES = TASK_STATUSES;
  @Input() taskStatus!: TaskStatus;
  tasks: Task[] = [
    { id: 1, title: 'Task 1', status: TASK_STATUSES['TO_DO'] },
    { id: 2, title: 'Task 2', status: TASK_STATUSES['TO_DO'] },
    { id: 3, title: 'Task 3', status: TASK_STATUSES['DONE'] },
  ];
  tasksByStatus!: { [key: string]: Task[] };

  ngOnInit() {
    this.tasksByStatus = Object.keys(TASK_STATUSES).reduce((acc, cur) => {
      acc[cur] = this.tasks.filter((x) => x.status.key === cur);
      return acc;
    }, {} as { [key: string]: Task[] });
  }

  drop(event: CdkDragDrop<Task[]>) {
    const sourceStatus = event.previousContainer.id;
    const targetStatus = event.container.id;
    const draggedTask = event.item.data as Task;

    if (event.previousContainer === event.container) {
      moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
    } else {
      transferArrayItem(
        event.previousContainer.data,
        event.container.data,
        event.previousIndex,
        event.currentIndex
      );
      draggedTask.status = this.TASK_STATUSES[targetStatus as keyof typeof TASK_STATUSES];
      this.tasksByStatus[sourceStatus] = this.tasksByStatus[sourceStatus].filter(t => t.id !== draggedTask.id);
      this.tasksByStatus[targetStatus].push(draggedTask);
    }
  }

  public assignTasksByStatus(status: string): Task[] {
    return this.tasksByStatus[status] || [];
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 11:05:24