I'm building and app where there are multiple items rendered in set of columns. (For sake of demonstration let's say 4 columns)
I'm trying to achieve functionality of dragging and dropping items onto each other which will result in merge of those two items.
typescricpt data structure
Details{
id:number;
columns:Column[];
}
Column{
id:number;
item:Item[];
}
Item{
id:number;
text:string;
}
So I have details component with :
<div fxLayout="row wrap" fxLayoutAlign="center" fxLayoutGap="5px" cdkDropListGroup>
<column *ngFor="let column of details.columns" [column]="column" fxFlex>
</column>
</div>
And column component:
<div>
Column Header
</div>
<div cdkDropList
(cdkDropListDropped)="drop($event)"
[cdkDropListData]="column.items"
*ngFor="let item of column.items">
<item cdkDrag [item]="item" [cdkDragData]="item">
</item>
</div>
For now I just print it
drop(event: CdkDragDrop<Item[]>) {
console.log(event);
}
Whenever I now print event
after drop , I do have details of current container and moved onto , but I would require information about where exactly ( on which item.id ) I dropped that element, and not make item evade as default cdkDragDrop behaves. Afterwards I would have events for merging stuff on backend etc.
And hints would be appreciated
I was able to find solution.
Collegue of mine proposed to pass item on which event occurred in drop(event)
So final solution would be :
<div cdkDropList
(cdkDropListDropped)="drop($event,item)"
[cdkDropListData]="column.items"
*ngFor="let item of column.items">
<item cdkDrag [item]="item" [cdkDragData]="item">
</item>
</div>
and handling ( using lodash )
drop(event: CdkDragDrop<Item[]>, dropedOn: Item) {
const dragged = event.item.data;
if (dragged.id != dropedOn.id) {
dropedOn.text = dropedOn.text + "\n" + dragged.text;
if (event.previousContainer === event.container) {
_.remove(event.container.data,(item)=>item.id== dragged.id);
} else {
_.remove(event.previousContainer.data,(item)=>item.id== dragged.id);
}
}
}
Updated stackblitz.
However the whole solution was still bit too clunky , and it was hard to clearly show which element was to be merged into and eventually moved to other sollution ng-drag-drop.
There every item is draggable and droppable and effect is bit nicer ( although requires extra searching of item to delete it from column)
<div *ngFor="let item of column.items;" style="margin-top: 2px">
<div draggable [dragData]="item" droppable (onDrop)="onItemDrop($event,item)">
<item [item]="item"></item>
</div>
</div>
And updated stackblitz with other solution