这是我在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);
这很好。可以创建可拖动的动态创建的组件吗?
谢谢。
答案 0 :(得分:1)
最后,由于MauriceNino的回复,它得以正常工作。我将把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>
最后,经过一周的搜索,终于可以使用了! 谢谢!
答案 1 :(得分:0)
虽然这对于一种单一类型的组件可以正常工作,但是如果您需要使用不同的动态类型的组件,请阅读下面的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>
答案 2 :(得分:0)
我已经通过用createComponent方法动态生成组件并通过ViewComponentRef方法处理移动来解决了这个问题:
container.component.html
if ($row['rank'] == 1 || $row['rank'] == 2 || $row['rank'] == 3) {
echo 'SHOW RANK NAME'; (Administrator, Moderador and Helper)
}
container.component.ts
<div cdkDropList (cdkDropListDropped)="drop($event)">
<ng-container #cmpContainer></ng-container>
</div>
dynamic.component.html
import {CdkDragDrop, moveItemInArray} from "@angular/cdk/drag-drop";
@ViewChild('cmpContainer', {static: true, read: ViewContainerRef}) cmpContainer: ViewContainerRef;
components: ComponentRef<Dynamic>[] = [];
addComponent() {
const factory = this.cfr.resolveComponentFactory(Dynamic);
const component: ComponentRef<Dynamic> = this.cmpContainer.createComponent(factory);
}
drop(event: CdkDragDrop<PollQuestionCardComponent[]>) {
this.cmpContainer.move(this.components[event.previousIndex].hostView, event.currentIndex);
moveItemInArray(this.components, prevIndex, currentIndex);
}
答案 3 :(得分:0)
您可以围绕每个 div
创建 ng-container
并为其设置 cdkDrag
属性。