Angular Drag & Drop:如何将cdkDrag元素放入嵌套cdkDropLists容器
Angular CDK 嵌套拖拽解决方案
该需求完全可以实现,你遇到的问题是Angular CDK拖拽默认事件冒泡、外层容器优先捕获放置事件导致的,按以下步骤配置即可解决:
- 给所有内层嵌套的
cdkDropList添加[cdkDropListNested]="true"属性,该属性是CDK专门为嵌套拖拽场景设计的,会告诉CDK优先识别内层的dropList作为放置目标,避免外层容器优先捕获放置事件。 - 在内层dropList的
cdkDropListDropped事件回调中调用$event.stopPropagation(),阻止事件冒泡到外层的dropList,避免外层同时触发drop事件。 - 如果使用了
cdkDropListGroup,不需要额外配置cdkDropListConnectedTo,Group会自动关联所有后代的dropList,确保拖拽元素可以在所有容器间互相放置。
代码示例
模板代码
<!-- 外层拖拽组 --> <div cdkDropListGroup> <!-- 第一个外层放置容器 --> <div cdkDropList id="outer-drop-1" [cdkDropListData]="outerList1" (cdkDropListDropped)="handleOuterDrop($event)" > <p>外层容器1</p> <!-- 内层放置容器1 --> <div cdkDropList id="inner-drop-1" [cdkDropListData]="innerList1" [cdkDropListNested]="true" (cdkDropListDropped)="handleInnerDrop($event)" style="border: 1px solid #ccc; padding: 10px; margin: 10px 0;" > <p>内层容器1</p> <div *ngFor="let item of innerList1" cdkDrag>{{item}}</div> </div> <!-- 内层放置容器2 --> <div cdkDropList id="inner-drop-2" [cdkDropListData]="innerList2" [cdkDropListNested]="true" (cdkDropListDropped)="handleInnerDrop($event)" style="border: 1px solid #ccc; padding: 10px; margin: 10px 0;" > <p>内层容器2</p> <div *ngFor="let item of innerList2" cdkDrag>{{item}}</div> </div> <div *ngFor="let item of outerList1" cdkDrag>{{item}}</div> </div> <!-- 第二个外层放置容器 --> <div cdkDropList id="outer-drop-2" [cdkDropListData]="outerList2" (cdkDropListDropped)="handleOuterDrop($event)" style="margin-top: 20px; border: 1px solid #eee; padding: 10px;" > <p>外层容器2</p> <div *ngFor="let item of outerList2" cdkDrag>{{item}}</div> </div> </div>
逻辑代码
import { Component } from '@angular/core'; import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { outerList1 = ['外层元素1', '外层元素2']; innerList1 = ['内层元素1-1', '内层元素1-2']; innerList2 = ['内层元素2-1', '内层元素2-2']; outerList2 = ['外层容器2元素1', '外层容器2元素2']; handleOuterDrop(event: CdkDragDrop<string[]>) { console.log('触发外层drop,容器id:', event.container.id); 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 ); } } handleInnerDrop(event: CdkDragDrop<string[]>) { // 阻止事件冒泡到外层容器 event.stopPropagation(); console.log('触发内层drop,容器id:', event.container.id); 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 ); } } }
配置完成后即可正常识别内层放置容器,拖拽元素可以在外层容器、内层容器之间自由放置。
内容的提问来源于stack exchange,提问作者Chris Burton
相关产品推荐
相关产品推荐

