[英]Angular 7 - Add drag and drop behaviour to dynamically created components
這是我在 SO 上提出的上一個問題的延續: 在聲明時向組件選擇器添加指令 - 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);
這工作正常。 是否有可能創建可拖動的動態創建的組件?
謝謝你。
我通過使用 createComponent 方法動態生成組件並通過 ViewComponentRef 方法處理移動來解決這個問題:
容器組件.html
<div cdkDropList (cdkDropListDropped)="drop($event)">
<ng-container #cmpContainer></ng-container>
</div>
容器.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);
}
動態組件.html
<div cdkDrag>
<div cdkDragHandle></div>
</div>
雖然這適用於單一類型的組件,但如果您需要使用不同的動態類型的組件,請閱讀下面的 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>
感謝 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>
終於,經過一周的搜索,終於成功了! 謝謝!
您可以在每個ng-container
周圍創建div
並在其上設置cdkDrag
屬性。
我需要將 cdk drag(使用 cdkdraglist 指令)指令應用於所有動態創建的元素。 所以這個cdk拖放將起作用。 但是 angular 不允許在運行時向模板中的 am 元素添加指令。 結論是,要實現此功能,我們必須支持網格系統。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.