Angular 7 Drag and Drop - Dynamically Create Drop Zones
After a full day of research, I found this pull request on Angular CDK repository on Github. Now, since I did not know how to integrate cdkDropListGroup into my example, I decited to create an array of IDs which will be added to [cdkDropListConnectedTo].
Each instance of my second list will have generated ID, and that ID will be added to array with suitable prefix (in my second list, on cdkDropList):
<div cdkDropList [attr.id]="addId(i, j)" [cdkDropListData]="appointment.lessons" [cdkDropListConnectedTo]="[subjectList]" (cdkDropListDropped)="drop($event)">
addId method:
addId(i, j) { this.LIST_IDS.push('cdk-drop-list-' + i + '' + j); return i + '' + j;}
(cdk-drop-list- is an ID prefix. CDK places this prefix on every element with cdkDropList attribute)
So, my array will look like:
- cdk-drop-list-00
- cdk-drop-list-01
- cdk-drop-list-02
- etc.
Now, I pass that array to [cdkDropListConnectedTo] in my first list:
<div class="subj-container" cdkDropListOrientation="horizontal" cdkDropList #subjectList="cdkDropList" [cdkDropListData]="subjects" [cdkDropListConnectedTo]="LIST_IDS" (cdkDropListDropped)="drop($event)">
And it works flawlessly!
Hope this will help anybody with the same problem. Also, take a look at the pull request I mentioned, my solution is only a workaround, there is probably a better solution with cdkDropListGroup
Source Link
Demo Link
For Dynamic Drag n Drop Lists, we can use ID instead of # Template variables
app.component.html
<div class="col-md-3" *ngFor="let week of weeks"> <div class="drag-container"> <div class="section-heading">Week {{week.id}}</div> <div cdkDropList id="{{week.id}}" [cdkDropListData]="week.weeklist" [cdkDropListConnectedTo]="connectedTo" class="item-list" (cdkDropListDropped)="drop($event)"> <div class="item-box" *ngFor="let weekItem of week.weeklist" cdkDrag>Week {{week.id}} {{weekItem}}</div> </div> </div></div>
app.component.ts
import { Component } from '@angular/core';import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css']})export class AppComponent { weeks = []; connectedTo = []; constructor() { this.weeks = [ { id: 'week-1', weeklist: [ "item 1", "item 2", "item 3", "item 4", "item 5" ] }, { id: 'week-2', weeklist: [ "item 1", "item 2", "item 3", "item 4", "item 5" ] }, { id: 'week-3', weeklist: [ "item 1", "item 2", "item 3", "item 4", "item 5" ] }, { id: 'week-4', weeklist: [ "item 1", "item 2", "item 3", "item 4", "item 5" ] }, ]; for (let week of this.weeks) { this.connectedTo.push(week.id); }; } drop(event: CdkDragDrop<string[]>) { if (event.previousContainer === event.container) { moveItemInArray(event.container.data, event.previousIndex, event.currentIndex); } else { transferArrayItem(event.previousContainer.data, event.container.data, event.previousIndex, event.currentIndex); } }}
With cdkDropListGroup you can now do:
<div cdkDropListGroup> <div cdkDropList [cdkDropListData]="data" (cdkDropListDropped)="drop($event)"> <div class="row m-2"> <div *ngFor="let i of data" cdkDrag>{{i}}</div> </div> </div> <div class="subj-container" cdkDropListOrientation="horizontal" cdkDropList #subjectList="cdkDropList" [cdkDropListData]="subjects" (cdkDropListDropped)="drop($event)"> </div></div>
No longer a need for cdkDropListConnectedTo in this case.See https://github.com/angular/material2/blob/master/src/cdk/drag-drop/drag-drop.md