'Angular drag and drop: Items should not remove from container after drag and dropped

I am using Angular drag and drop CDK:

I am able to drag and drop items from one container to another and vice versa. Now, I am trying to not to remove a dropped item from a container, but it should be dropped into another container.

enter image description here

As you can see in the picture, I want to drag an item "Go home" from 'To do' container to 'Done' container.

I want to keep an item after dropped.

Example: https://stackblitz.com/angular/bypeyxpbvxe?file=src%2Fapp%2Fcdk-drag-drop-connected-sorting-example.html

Any help, please...



Solution 1:[1]

This is quite easy. Just use copyArrayItem instead of transferArrayItem

import {
  CdkDragDrop,
  copyArrayItem,
  moveItemInArray
} from '@angular/cdk/drag-drop';

drop(event: CdkDragDrop<string[]>) {
    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
      );
    }
  }

Solution 2:[2]

use copyArrayItem instead of transferArrayItem.
Change:

transferArrayItem(
    event.previousContainer.data,
    event.container.data,
    event.previousIndex,
    toIndex
); 

to

copyArrayItem(
    event.previousContainer.data,
    event.container.data,
    event.previousIndex,
    toIndex
);

Solution 3:[3]

If you don't want the item removed while copying, use the cdkDragStarted like this in your HTML:

(cdkDragStarted)="dragStarted($event, dataList, index)"

and the method:

dragStarted(event: CdkDragStart, dataList, index) {
 if (this.dropMode  === 'copy') {
   dataList.splice(index, 0, event.source.data);
 }
}

onDropped(event) {
  event.previousContainer.dataList.splice(event.previousIndex,1);

  // your code to copy the item...
}

Solution 4:[4]

I managed to make this work by using cdkDragStarted and cdkDragDropped

HTML:

 <mat-row
        cdkDrag
        cdkDragHandle
        (cdkDragStarted)="dragStarted($event)"
        (cdkDragDropped)="dragStopped($event)"
    >
    </mat-row>

TS:

dragStarted(event: any) {
this.dataSource.data.splice(
  this.dataSource.data.findIndex(
    (d: TableRow) => d.ID === event.source.data[0].ID
  ) + 1,
  0,
  event.source.data[0]
);
this.table?.renderRows();
}

dragStopped(event: any) {
this.dataSource.data.splice(
  this.dataSource.data.findIndex(
    (d: TableRow) => d.ID === event.item.data[0].ID
  ),
  1
);
this.table?.renderRows();
}

Solution 5:[5]

I don't think is possible with angular-material. Here is a possible solution

<div class="example-box" *ngFor="let item of todo" cdkDrag>{{item}} <span (click)="copyMe(item)">Copy</span> </div>

 copyMe(item: any) {
    console.log(item)
    const newItem = item
    this.todo.push(newItem)
  }

Stackblitz: https://stackblitz.com/angular/xlkxgkneavr?file=src%2Fapp%2Fcdk-drag-drop-connected-sorting-group-example.ts

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Florian
Solution 2 Tyler2P
Solution 3 Cees Bolijn
Solution 4 Max Sbadl
Solution 5 jacopotaba