Angular CDK拖拽至Material Dialog及动态组件实现问题求助
Angular CDK拖拽无法拖入Material Dialog的解决办法
核心问题就是Material Dialog是动态生成的,编译阶段不在WorkbenchComponent的模板树里,导致它内部的cdkDropList没被父容器的cdkDropListGroup纳入管理,跨Dialog的拖拽自然失效。下面给两个可行的解决思路:
思路1:手动把Dialog里的cdkDropList注册到父级group
cdkDropListGroup是靠CdkDropListGroup服务来管理所有drop list的,所以直接在SubwindowComponent里把自身的drop list注册进去就行:
- 在SubwindowComponent里注入需要的服务和指令:
import { Component, OnInit, OnDestroy, Inject } from '@angular/core'; import { CdkDropListGroup, CdkDropList } from '@angular/cdk/drag-drop'; @Component({ selector: 'app-subwindow', templateUrl: './subwindow.component.html' }) export class SubwindowComponent implements OnInit, OnDestroy { constructor( @Inject(CdkDropListGroup) private dropListGroup: CdkDropListGroup<CdkDropList>, private dropList: CdkDropList ) {} ngOnInit(): void { // 把当前drop list注册到Workbench的group里 this.dropListGroup.register(this.dropList); } ngOnDestroy(): void { // 组件销毁时一定要注销,防止内存泄漏 this.dropListGroup.remove(this.dropList); } }
- 确保SubwindowComponent的模板里有
cdkDropList指令,和拖拽元素的cdkDrag匹配好。
思路2:用ViewContainerRef把Dialog内容嵌入Workbench的模板树
如果你的Dialog内容允许作为Workbench的子视图存在,就用ViewContainerRef动态创建组件,这样生成的SubwindowComponent就属于Workbench的模板树,cdkDropListGroup会自动识别它:
- 在WorkbenchComponent里注入相关服务:
import { Component, ViewContainerRef, ComponentFactoryResolver } from '@angular/core'; import { SubwindowComponent } from './subwindow/subwindow.component'; @Component({ selector: 'app-workbench', templateUrl: './workbench.component.html' }) export class WorkbenchComponent { constructor( private viewContainerRef: ViewContainerRef, private componentFactoryResolver: ComponentFactoryResolver ) {} openSubwindow(): void { // 生成SubwindowComponent的工厂 const factory = this.componentFactoryResolver.resolveComponentFactory(SubwindowComponent); // 在当前视图容器里创建组件,这样就属于Workbench的模板树了 const componentRef = this.viewContainerRef.createComponent(factory); // 按需设置组件的输入属性 // componentRef.instance.yourInput = someValue; } }
这种方式下,不需要额外注册drop list,group会自动关联。
额外提醒
- 不管用哪种方法,要保证所有参与拖拽的
cdkDropList要么设置了相同的cdkDropListConnectedTo,要么依赖group自动关联。 - 如果是用
MatDialog服务打开的弹窗,思路1更合适,因为MatDialog默认把组件挂在根节点,不属于Workbench的模板树,手动注册最直接。 - 思路1一定要在组件销毁时注销drop list,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Daniel Methner
相关产品推荐
相关产品推荐

