Angular 7 - Add Drag And Drop Behaviour To Dynamically Created Components
Solution 1:
I'm done with this problem by generating components dynamically with createComponent method and processing move by ViewComponentRef method:
container.component.html
<divcdkDropList (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>
- In this case, you can access component instance directly through the components array.
Solution 2:
Update
While this works fine with one single type of component, if you need to use different dynamic types of components, read Chaitanya Bangera's comment down below!
Original Comment
Should work with something like this (CmpComponent would be your component that you want to insert):
components: CmpComponent[];
const childComponent = this.componentFactoryResolver.resolveComponentFactory(CustomComponent);
this.components.push(childComponent);
drop(event: CdkDragDrop<CmpComponent[]>) {
moveItemInArray(this.components, event.previousIndex, event.currentIndex);
}
<divcdkDropListstyle="margin: 20px" (cdkDropListDropped)="drop($event)"><divcdkDrag *ngFor="let cmp of components"><app-cmp></app-cmp></div></div>
Solution 3:
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 component.
While getting Maurice's solution to work for multiple components, I came across this magical concept called ng-container! What a life-saver!! My solution is as follows:
components=[];
const childComponent = this.componentFactoryResolver.resolveComponentFactory(CustomComponent);
this.components.push(childComponent);
drop(event: CdkDragDrop<CmpComponent[]>) {
moveItemInArray(this.components, event.previousIndex, event.currentIndex);
}
Now for the template:
<divcdkDropListclass="example-list"style="margin: 20px" (cdkDropListDropped)="drop($event)"><ng-container *ngFor="let cmp of components"><ng-container *ngIf="cmp.componentType.name=='Component1'"><app-Component1cdkDrag></app-Component1></ng-container><ng-container *ngIf="cmp.componentType.name=='Component2'"><app-Component2cdkDrag></app-Component2></ng-container><ng-container *ngIf="cmp.componentType.name=='Component3'"><app-Component3cdkDrag></app-Component3></ng-container></ng-container></div>
Finally, after a week of searching, it finally works! Thank you!
Solution 4:
You can just create div
around every ng-container
and set cdkDrag
attribute on it.
Solution 5:
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).
Post a Comment for "Angular 7 - Add Drag And Drop Behaviour To Dynamically Created Components"