// Tutorial //

How To Add Drag and Drop Using the Angular CDK

Published on January 10, 2019
Default avatar
By Sumit Vekariya
MEAN + Serverless + GraphQL
How To Add Drag and Drop Using the Angular CDK

This tutorial is out of date and no longer maintained.

Introduction

The @angular/cdk/drag-drop package from the Angular Component Development Kit (CDK) provides you the functionality to easily create drag and drop interfaces with full flexibility. It gives you an API that makes it much easier to create complex drag and drop interfaces without having to reinvent the wheel.

In this post, we’ll briefly cover what you need to get started for drag and drop in Angular using the CDK.

Setting Up the Project

First, make sure that the package for the CDK itself is added to your project:

  1. npm install @angular/cdk

Or, using Yarn:

  1. yarn add @angular/cdk

To use the APIs for drag and drop functionality provided by Angular, import the DragDropModule like this in your app module:

app.module.ts
import { DragDropModule } from '@angular/cdk/drag-drop';

After that also add it to the list of imports:

app.module.ts
imports: [
  DragDropModule
]

Implementing the Drag and Drop Interface

Here’s the interface we’ll be creating as part of this post:

Animated gif of drag and drop interface.

Drag and Drop Interface with 4 Task Trackers

So, now that all the APIs are available we can use all the directives and modules provided by DragDropModule, and by using it we’re going to create 4 task tracks In Progress, Todo, D-Done, and QA Pass.

Note: Here I’m using the mat-card and mat-card-content components to show the tasks. In order to use this, you must also have Angular Material added to your project.

Here’s a first drag and drop example:

app.component.html
<!-- 4 Task trackers are there named "Todo", "In Progress", "D-Done", and "QA-Pass" -->

<div class="board">
  <div class="card-list mat-elevation-z1" *ngFor="let track of tracks; let i=index">

    <h2 cdkDragHandle class="mat-h2">{{track.title}}</h2>

    <div class="card-list-content" cdkDropList [id]="track.id" [cdkDropListData]="track.tasks" [cdkDropListConnectedTo]="trackIds"
      (cdkDropListDropped)="onTaskDrop($event)" [ngStyle]="{'background-color': trackColor[i]}">

      <mat-card style="margin: 2%;" *ngFor="let task of track.tasks" cdkDrag>
        <!-- Use the mat-card-content to add the proper spacing. -->
        <mat-card-content>
          <h2>{{task.title}}</h2>
          {{task.description}}
        </mat-card-content>
      </mat-card>
    </div>

  </div>
</div>

And below is the data which we are using to render the trackers and tasks:

[
  {
    "title": "Todo",
    "id": "todo",
    "tasks": [
      {
        "id": "first-task",
        "title": "First Task",
        "description": "This is my first task"
      }
    ]
  },
  {
    "title": "In Progress",
    "id": "inprogress",
    "tasks": [
      {
        "id": "seconf-task",
        "title": "Second Task",
        "description": "This is my first task"
      }
    ]
  },
  {
    "title": "D-Done",
    "id": "ddone",
    "tasks": [
      {
        "id": "third-task",
        "title": "Third Task",
        "description": "This is my first task"
      }
    ]
  },
  {
    "title": "QA Pass",
    "id": "qapass",
    "tasks": [
      {
        "id": "fourth-task",
        "title": "Fourth Task",
        "description": "This is my first task"
      }
    ]
  }
]
  • The cdkDropList directive is applied to a container that wraps a set of draggable items. You can add cdkDropList elements to constrain where elements may be dropped. In our example, it will be the Task Tracks.
  • The cdkDropList directive has many properties and cdkDropListData is one of them, Which is used to add data arbitrarily to the container. In our example, we are attaching Task Tracks as our data.
  • cdkDropListDropped is an event that gets emitted when the user drops an item inside the container. In our example whenever any task gets dropped inside any of the task tracks, it will call the onTaskDrop($event) method.

Here’s an example method for handling the drop event:

app.component.ts
onTaskDrop(event: CdkDragDrop<Task[]>) {
  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);
  }
}

Note the conditional statement as part of the method. In case the destination container is different from the previous container, we need to transfer the given task to the target data array. This happens if a task has been dropped on a different track.

And that’s it! You now have working drag and drop functionality.

Conclusion

Make sure you check out the official Angular Drag and Drop documentation to dig deeper into what can be done.

You can find the complete source code for this example project in this repo GitHub.


Want to learn more? Join the DigitalOcean Community!

Join our DigitalOcean community of over a million developers for free! Get help and share knowledge in our Questions & Answers section, find tutorials and tools that will help you grow as a developer and scale your project or business, and subscribe to topics of interest.

Sign up
About the authors
Default avatar
MEAN + Serverless + GraphQL

A tech enthusiast, expertise in MEAN + Serverless + GrapQL + Websockets

Still looking for an answer?

Was this helpful?
Leave a comment