Reputation: 510
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.
Upvotes: 31
Views: 18948
Reputation: 1852
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
Upvotes: 9
Reputation: 201
You need to find location of target & source then copy the value
Case 1: Copy from one draggable list to another draggable list
drop(event: any) {
if (event.previousContainer === event.container) {
moveItemInArray(
event.container.data,
event.previousIndex,
event.currentIndex
);
} else {
const prev_idx = event.previousIndex;
const curr_id = event.currentIndex;
// Copy the data.
event.container.data[curr_id] = event.previousContainer.data[prev_idx];
}
}
}
Case 2: Copy your Data from list to a specific variable
drop(event: any) {
// Copy the data to my-variable
const prev_idx = event.previousIndex;
this.my-variable = event.previousContainer.data[prev_idx];
}
}
}
Upvotes: 0
Reputation: 640
Import import {copyArrayItem} from '@angular/cdk/drag-drop';
AND
Replace transferArrayItem
with copyArrayItem
Upvotes: 7
Reputation: 336
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
);
}
}
Upvotes: 30