如何在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
相关产品推荐
相关产品推荐

