I am trying to implement an editor where one can drag an item to add it to the main content, the problem is that the source item is always destroyed when I'm dragging out of the source item container.
Is there a way to force the source item to stay where it is while it's still possible to drag and drop the item? Basically, I want a copy-behaviour of that instead of a move-behaviour.
I've already seen other questions that correspond to what I want to achieve basically, but none of them really helped me as the questions were more about how to get it technically done to copy an item while I want to know how I implement this behaviour in the UI as its very confusing to see if the item just disappears.
When you check in the browser, it allows you to drag the item. It will not drop it in the list and will remain as it is when you leave the mouse pointer. The function onDrop takes care of dropping the item dragged in the position required.
The @angular/cdk/drag-drop module provides you with a way to easily and declaratively create drag-and-drop interfaces, with support for free dragging, sorting within a list, transferring items between lists, animations, touch devices, custom drag handles, previews, and placeholders, in addition to horizontal lists and ...
Disable dragging If you want to disable dragging for a particular drag item, you can do so by setting the cdkDragDisabled input on a cdkDrag item. Furthermore, you can disable an entire list using the cdkDropListDisabled input on a cdkDropList or a particular handle via cdkDragHandleDisabled on cdkDragHandle.
To implement drag and drop list you have to include your ngFor repeated section inside a parent div to make that section draggable. This is just a basic structure of how the draggable section should look. Now we have to provide DndList directives to this structure. Basic functioning HTML for drag and drop list.
replace
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
drop(event: any) {
if (event.previousContainer === event.container) {
moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
} else {
copyArrayItem(
event.previousContainer.data,
event.container.data,
event.previousIndex,
event.currentIndex
);
}
}
Import import {copyArrayItem} from '@angular/cdk/drag-drop';
AND
Replace transferArrayItem
with copyArrayItem
All solutions above are great however there is one problem cloning happens after element is dropped so I went through git conversion and found the solution below
STYLES
.drag-container {
width: 400px;
max-width: 100%;
margin: 0 25px 25px 0;
display: inline-block;
vertical-align: top;
}
.drag-list {
border: solid 1px #ccc;
min-height: 60px;
background: white;
border-radius: 4px;
overflow: hidden;
display: block;
}
.drag-box {
padding: 20px 10px;
border-bottom: solid 1px #ccc;
color: rgba(0, 0, 0, 0.87);
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
cursor: move;
background: white;
font-size: 14px;
}
.cdk-drag-preview {
box-sizing: border-box;
border-radius: 4px;
box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
0 8px 10px 1px rgba(0, 0, 0, 0.14),
0 3px 14px 2px rgba(0, 0, 0, 0.12);
}
.cdk-drag-placeholder {
opacity: 0;
}
.cdk-drag-animating {
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}
.drag-box:last-child {
border: none;
}
.drag-list.cdk-drop-list-dragging .drag-box:not(.cdk-drag-placeholder) {
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}
TYPESCRIPT
menu: any = [
{ title: 'pork', price: 12, id: 1 },
{ title: 'duck', price: 12, id: 2 },
{ title: 'chicken', price: 12, id: 3 },
{ title: 'beef', price: 12, id: 4 },
{ title: 'soup', price: 12, id: 5 },
];
table: any = [];
drop(event: any) {
if (event.previousContainer !== event.container) {
copyArrayItem(
event.previousContainer.data,
event.container.data,
event.previousIndex,
event.currentIndex
);
} else {
moveItemInArray(
event.container.data,
event.previousIndex,
event.currentIndex
);
}
if (event.previousContainer.data) {
this.menu = this.menu.filter((f: any) => !f.temp);
}
}
exited(event: any) {
const currentIdx = event.container.data.findIndex(
(f: any) => f.id === event.item.data.id
);
this.menu.splice(currentIdx + 1, 0, {
...event.item.data,
temp: true,
});
}
entered() {
this.menu = this.menu.filter((f: any) => !f.temp);
}
HTML
<div cdkDropListGroup>
<div class="drag-container">
<h2>To do</h2>
<div class="drag-list" cdkDropList #menuList="cdkDropList" [cdkDropListData]="menu" cdkDropListSortingDisabled [cdkDropListConnectedTo]="[tableList]" (cdkDropListDropped)="drop($event)" (cdkDropListExited)="exited($event)" (cdkDropListEntered)="entered()">
<div class="drag-box" *ngFor="let item of menu" cdkDrag [cdkDragData]="item">{{item.title}}</div>
</div>
</div>
<div class="drag-container">
<h2>Done</h2>
<div class="drag-list" cdkDropList #tableList="cdkDropList" [cdkDropListData]="table" (cdkDropListDropped)="drop($event)">
<div class="drag-box" *ngFor="let item of table; let idx = index" cdkDrag>{{item.title}}</div>
</div>
</div>
</div>
Source 1 : stackblitz
Source 2 : github
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With