I've been trying to do cool things with the CDK and cdkDragDrop for a while now and the genius behind this library is finally starting to click.
My first step was to make a simple list work via the documentation on the Angular Material site. This code worked just fine but didn't actually meet any of my needs.
Next up, I delved a little deeper via some code provided by the awesome @joeyperrot, I got this ridiculously cool drag drop dashboard up and working on stackblitz.

  1. I needed cdkDragDrop

I didn't think I needed it, but I was wrong.
I've used Dragula and even implemented some simple drag and drop using the underlying primitives, but when I wanted to build my game, I started running into problems.
Here's a few of the reasons I ended up choosing the CDK for drag and drop.

Transparency & Previews

I've been trying to build a game, and I had little images I wanted users to be able to drag around. When I first implemented this by hand, I discovered that the native drag and drop capabilities move the image to a new layer with opacity 1, losing the transparency in my image.
I did a little searching on how to fix this. To fix the transparency problem, you just clone the item you are dragging, hide the original for the duration of the drag, then match the clone up to the mouse cursor position and update it as the cursor moves. Easy right? Hahahahaha. The CDK does this automatically, meaning my transparent images just started working.


Next I realized I wanted to show the user where it was valid to place units, so I wanted the preview to snap into my target tiles. The CDK does this by default too.
my hexagon territory game

  1. It's not just for lists

The built-in support for lists is pretty good. When you reorder list elements there are a couple helpful methods that give you the old indexes and the new ones, even between lists.
if (event.previousContainer === event.container) {
  moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
} else {

But if you don't need these methods, the CDK offers all of the underlying primitives in the form of cdkDrag and cdkDropList. With the combination of these two directives, you can build any type of drag and drop system you could possibly want.

  1. Everything needs to be a cdkDropList

Every element you want to be draggable or to be a drop target MUST be the child of a cdkDropList.
The name DropList is a little confusing, because it doesn't need to be a list. For example, when I have a game board made up of hexagonal tiles, I made each tile into its own DropList so that it can receive drops.
You should also remember that your cdkDrag element must be contained in its own dropList. This was a little weird at first, because why would my draggables need to be a dropList if the user isn't dropping things there?
I don't know the full reason but my guess is that if the user action is cancelled, the item needs to be able to return to its origin, so that origin must be a dropList.

  1. Your cdkDropLists need to be connected

You can manually do this by providing a [cdkDropListConnectedTo]="[namedList1,namedList2,etc] on every cdkDropList, or you can wrap everything in a single cdkDropListGroup.
Here's a super contrived example to show the automatic connections between lists. You should just use a single cdkDropList normally.
<ng-container cdkDropListGroup>
  <div *ngFor="let item of items;index as i" cdkDropList>
    {{i}}: <div cdkDrag>{{item}}</div>

  1. Your draggables can carry data

When I built my own custom drag and drop in the past, I always made a global variable called something like carrying which stored all of the data correlated to an item currently being dragged by a user.
Global variables aren't a great way to manage this information, and I would sometimes end up in weird states where I would still be carrying an item even after the user cancelled the action.
By setting [cdkDragData] you can pass any shape of information or objects that will be available to the receiving DropList after the user completes their interaction.
<div *ngFor="let pawn of pawns">
  <div [cdkDragData]="pawn" cdkDrag>{{pawn.name}}</div>

This approach has better potential

I haven't tried this, but theoretically the CDK could support multi-touch multi-drag with multiple simultaneous elements being dragged around the screen. This is one of the benefits of letting the library handle it instead of you, is that ultimately they can cover more use cases that you don't even know you need before you need them.


I'm not sure why I was so skeptical of the CDK's Drag and Drop capabilities at first, but now having used it more extensively, I have no idea how I lived without it. Give it a try and let me know what you think.