admin管理员组

文章数量:1293530

This is in continuation of the previous question I asked on SO: Add directives to ponent selector when it is declared - Angular 7

I am dynamically creating ponents on a button click. The ponents are displayed one below another in a list like manner. I want to introduce drag-drop behaviour so that the user can rearrange the ponents after creating them.

In the previous question, I tried using Angular-Material, but realised it might not be possible to use it for ponents, due to the issue of adding "cdkDrag" directive to the ponent's selector tag, and the fact that the cdkDropList and cdkDrag might need to be in the same template.

I have a div as such in the template:

<div cdkDropList style="margin: 20px" (cdkDropListDropped)="drop($event)">
    <div #container></div>
</div>

And, I am creating custom ponents as follows:

@ViewChild('container', {read: ViewContainerRef})
  container: ViewContainerRef;

const childComponent = thisponentFactoryResolver.resolveComponentFactory(CustomComponent);
const ponent = this.container.createComponent(childComponent);

This works fine. Is it possible at all to create draggable dynamically created ponents?

Thank you.

This is in continuation of the previous question I asked on SO: Add directives to ponent selector when it is declared - Angular 7

I am dynamically creating ponents on a button click. The ponents are displayed one below another in a list like manner. I want to introduce drag-drop behaviour so that the user can rearrange the ponents after creating them.

In the previous question, I tried using Angular-Material, but realised it might not be possible to use it for ponents, due to the issue of adding "cdkDrag" directive to the ponent's selector tag, and the fact that the cdkDropList and cdkDrag might need to be in the same template.

I have a div as such in the template:

<div cdkDropList style="margin: 20px" (cdkDropListDropped)="drop($event)">
    <div #container></div>
</div>

And, I am creating custom ponents as follows:

@ViewChild('container', {read: ViewContainerRef})
  container: ViewContainerRef;

const childComponent = this.ponentFactoryResolver.resolveComponentFactory(CustomComponent);
const ponent = this.container.createComponent(childComponent);

This works fine. Is it possible at all to create draggable dynamically created ponents?

Thank you.

Share asked May 13, 2019 at 8:18 javapyscriptjavapyscript 7378 silver badges22 bronze badges
Add a ment  | 

5 Answers 5

Reset to default 3

I'm done with this problem by generating ponents dynamically with createComponent method and processing move by ViewComponentRef method:

container.ponent.html

<div cdkDropList (cdkDropListDropped)="drop($event)">
    <ng-container #cmpContainer></ng-container>
</div>

container.ponent.ts

import {CdkDragDrop, moveItemInArray} from "@angular/cdk/drag-drop";
import {DynamicComponent} from './dynamic.ponent.ts';

@ViewChild('cmpContainer', {static: true, read: ViewContainerRef}) cmpContainer: ViewContainerRef;
ponents: ComponentRef<DynamicComponent>[] = [];

addComponent() {
    const factory = this.cfr.resolveComponentFactory(DynamicComponent);
    const ponent: ComponentRef<DynamicComponent> = this.cmpContainer.createComponent(factory);
    this.ponents.push(ponent);
}

drop(event: CdkDragDrop<DynamicComponent[]>) {
    this.cmpContainer.move(this.ponents[event.previousIndex].hostView, event.currentIndex);
    moveItemInArray(this.ponents, prevIndex, currentIndex);
}

dynamic.ponent.html

<div cdkDrag>
    <div cdkDragHandle></div>
</div>
  • In this case, you can access ponent instance directly through the ponents array.

Finally got it to work, thanks to the reply from MauriceNino. I am going to mark Maurice's answer as accepted, since their solution works fine for a single ponent.

While getting Maurice's solution to work for multiple ponents, I came across this magical concept called ng-container! What a life-saver!! My solution is as follows:

ponents=[];

const childComponent = this.ponentFactoryResolver.resolveComponentFactory(CustomComponent);
this.ponents.push(childComponent);


drop(event: CdkDragDrop<CmpComponent[]>) {
  moveItemInArray(this.ponents, event.previousIndex, event.currentIndex);
}

Now for the template:

<div cdkDropList class="example-list" style="margin: 20px" (cdkDropListDropped)="drop($event)">
    <ng-container *ngFor="let cmp of ponents">
        <ng-container *ngIf="cmp.ponentType.name=='Component1'">
            <app-Component1 cdkDrag></app-Component1>
        </ng-container>
        <ng-container *ngIf="cmp.ponentType.name=='Component2'">
            <app-Component2 cdkDrag></app-Component2>
        </ng-container>
        <ng-container *ngIf="cmp.ponentType.name=='Component3'">
            <app-Component3 cdkDrag></app-Component3>
        </ng-container>

    </ng-container>
</div>

Finally, after a week of searching, it finally works! Thank you!

Update

While this works fine with one single type of ponent, if you need to use different dynamic types of ponents, read Chaitanya Bangera's ment down below!

Original Comment

Should work with something like this (CmpComponent would be your ponent that you want to insert):

  ponents: CmpComponent[];

const childComponent = this.ponentFactoryResolver.resolveComponentFactory(CustomComponent);
this.ponents.push(childComponent);


drop(event: CdkDragDrop<CmpComponent[]>) {
  moveItemInArray(this.ponents, event.previousIndex, event.currentIndex);
}
<div cdkDropList style="margin: 20px" (cdkDropListDropped)="drop($event)">
    <div cdkDrag *ngFor="let cmp of ponents">
        <app-cmp></app-cmp>
    </div>
</div>

You can just create div around every ng-container and set cdkDrag attribute on it.

Requirement was to create draggable editable Row(s). User can add/delete row.

Here to apply cdk drag (with cdkdraglist directive ) directive to all the dynamically created elements. so this cdk drag and drop will work. but angular is not allowing runtime addition of directive to am element in template. concluding that ,to achive this feature we have to take support in of a grid framework(like ag-grid).

本文标签: javascriptAngular 7Add drag and drop behaviour to dynamically created componentsStack Overflow