簡體   English   中英

Angular 7 - 向動態創建的組件添加拖放行為

[英]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>
  • 在這種情況下,您可以直接通過 components 數組訪問組件實例。

更新

雖然這適用於單一類型的組件,但如果您需要使用不同的動態類型的組件,請閱讀下面的 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM