Angular 7 - 向动态创建的组件添加拖放行为
Posted
技术标签:
【中文标题】Angular 7 - 向动态创建的组件添加拖放行为【英文标题】:Angular 7 - Add drag and drop behaviour to dynamically created components 【发布时间】:2019-09-30 04:11:01 【问题描述】:这是我在 SO 上提出的上一个问题的延续: Add directives to component selector when it is declared - Angular 7
我在单击按钮时动态创建组件。组件以类似列表的方式在另一个下方显示。我想引入拖放行为,以便用户可以在创建组件后重新排列组件。
在上一个问题中,我尝试使用 Angular-Material,但意识到可能无法将它用于组件,因为在组件的选择器标签中添加“cdkDrag”指令的问题,以及 cdkDropList和 cdkDrag 可能需要在同一个模板中。
我在模板中有一个这样的 div:
<div cdkDropList style="margin: 20px" (cdkDropListDropped)="drop($event)">
<div #container></div>
</div>
而且,我正在按如下方式创建自定义组件:
@ViewChild('container', read: ViewContainerRef)
container: ViewContainerRef;
const childComponent = this.componentFactoryResolver.resolveComponentFactory(CustomComponent);
const component = this.container.createComponent(childComponent);
这很好用。是否有可能创建可拖动的动态创建的组件?
谢谢。
【问题讨论】:
【参考方案1】:我通过使用 createComponent 方法动态生成组件并通过 ViewComponentRef 方法处理移动来解决这个问题:
container.component.html
<div cdkDropList (cdkDropListDropped)="drop($event)">
<ng-container #cmpContainer></ng-container>
</div>
container.component.ts
import CdkDragDrop, moveItemInArray from "@angular/cdk/drag-drop";
import DynamicComponent from './dynamic.component.ts';
@ViewChild('cmpContainer', static: true, read: ViewContainerRef) cmpContainer: ViewContainerRef;
components: ComponentRef<DynamicComponent>[] = [];
addComponent()
const factory = this.cfr.resolveComponentFactory(DynamicComponent);
const component: ComponentRef<DynamicComponent> = this.cmpContainer.createComponent(factory);
this.components.push(component);
drop(event: CdkDragDrop<DynamicComponent[]>)
this.cmpContainer.move(this.components[event.previousIndex].hostView, event.currentIndex);
moveItemInArray(this.components, prevIndex, currentIndex);
dynamic.component.html
<div cdkDrag>
<div cdkDragHandle></div>
</div>
在这种情况下,您可以直接通过 components 数组访问组件实例。
【讨论】:
【参考方案2】:更新
虽然这适用于单一类型的组件,但如果您需要使用不同的动态类型的组件,请阅读下面 Chaitanya Bangera 的评论!
原评论
应该使用这样的东西(CmpComponent 将是您要插入的组件):
components: CmpComponent[];
const childComponent = this.componentFactoryResolver.resolveComponentFactory(CustomComponent);
this.components.push(childComponent);
drop(event: CdkDragDrop<CmpComponent[]>)
moveItemInArray(this.components, event.previousIndex, event.currentIndex);
<div cdkDropList style="margin: 20px" (cdkDropListDropped)="drop($event)">
<div cdkDrag *ngFor="let cmp of components">
<app-cmp></app-cmp>
</div>
</div>
【讨论】:
谢谢,我看看,虽然我觉得我可能会遇到困难,因为用户可以动态创建几个可用组件之一。它就像用户可以单击和创建的小部件列表,因此模板中的 可能不起作用。编辑:不过,我会为单个组件尝试它,以检查该方法是否有效。 我让它使用你的代码作为基础并使用 ng-container 而不是 *ngFor 的组件选择器来工作,它终于可以工作了。我会将您的答案标记为已接受,因为它适用于单个模板。我在下面添加了适用于不同组件的答案。 @ChaitanyaBangera 很高兴它成功了!我更新了我的答案,以便有相同问题的人更容易找到您的评论。 @ChaitanyaBangera 你能告诉我你是如何以这种方式处理组件参数的吗?我的意思是,您是使用动态生成值的输入/输出,还是有某种方法可以访问组件实例?和你有同样的问题,不知道如何处理组件参数。【参考方案3】:感谢 MauriceNino 的回复,终于可以使用了。我将 Maurice 的回答标记为已接受,因为他们的解决方案适用于单个组件。
在让 Maurice 的解决方案适用于多个组件时,我遇到了一个名为 ng-container 的神奇概念!多么救命啊!!我的解决方案如下:
components=[];
const childComponent = this.componentFactoryResolver.resolveComponentFactory(CustomComponent);
this.components.push(childComponent);
drop(event: CdkDragDrop<CmpComponent[]>)
moveItemInArray(this.components, event.previousIndex, event.currentIndex);
现在是模板:
<div cdkDropList class="example-list" style="margin: 20px" (cdkDropListDropped)="drop($event)">
<ng-container *ngFor="let cmp of components">
<ng-container *ngIf="cmp.componentType.name=='Component1'">
<app-Component1 cdkDrag></app-Component1>
</ng-container>
<ng-container *ngIf="cmp.componentType.name=='Component2'">
<app-Component2 cdkDrag></app-Component2>
</ng-container>
<ng-container *ngIf="cmp.componentType.name=='Component3'">
<app-Component3 cdkDrag></app-Component3>
</ng-container>
</ng-container>
</div>
终于,经过一周的搜索,终于成功了! 谢谢!
【讨论】:
drop(event: CdkDragDrop您可以在每个ng-container
周围创建div
并为其设置cdkDrag
属性。
【讨论】:
【参考方案5】:要求是创建可拖动的可编辑行。用户可以添加/删除行。
在这里将 cdk drag(带有 cdkdraglist 指令)指令应用于所有动态创建的元素。所以这个 cdk 拖放将起作用。但是 Angular 不允许运行时将指令添加到模板中的 am 元素。结论是,为了实现这个功能,我们必须支持网格框架(如 ag-grid)。
【讨论】:
这没有提供问题的答案。一旦你有足够的reputation,你就可以comment on any post;相反,provide answers that don't require clarification from the asker.以上是关于Angular 7 - 向动态创建的组件添加拖放行为的主要内容,如果未能解决你的问题,请参考以下文章