This tutorial is out of date and no longer maintained.
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.
First, make sure that the package for the CDK itself is added to your project:
- npm install @angular/cdk
Or, using Yarn:
- 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:
import { DragDropModule } from '@angular/cdk/drag-drop';
After that also add it to the list of imports:
imports: [
DragDropModule
]
Here’s the interface we’ll be creating as part of this post:
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:
<!-- 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"
}
]
}
]
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
.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:
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.
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.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!