Angular 16 Drag and Drop Tutorial with Material Library
As we know, Angular Material offers lots of useful UI components to build an app from scratch. I will take help of the Angular Material 13 theme to develop drag and drop.
Angular Material Drag and Drop Example
- Set up Angular Project
- Set up Angular CDK Drag and Drop API
- Create Drag and Drop Reordering Lists
- Transfer Items Between Lists using cdkDropList
- Angular Drag and Drop Code Files
- Demo Angular Material Drag and Drop
1. Set up Angular project and Angular Material Library
ng new angular-drag-drop
Angular CLI will ask you the following questions…
Would you like to add Angular routing?
Select y and Hit Enter.
Which stylesheet format would you like to use? (Use arrow keys)
Choose CSS and hit Enter
cd angular-drag-drop
In order to remove strict type warnings or errors make sure to set
“strict”: false
and"strictTemplates": false
under compilerOptions and angularCompilerOptions properties in tsconfig.json file.
Install Angular Material and Angular Animations
npm install --save @angular/material @angular/cdk @angular/animations
Let us see how to import Angular Material in Angular Drag and Drop App.
app.module.ts
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
@NgModule({
declarations: [...],
imports: [
BrowserAnimationsModule
],
providers: [...],
bootstrap: [...],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
Importing Angular Material 13 theme
Angular material comes with deeppurple-amber, purple-green, pink-bluegrey and indigo-pink theme. In order to apply material theme in angular drag and drop app, we must include a theme in your global styles.css
file.
@import "~@angular/material/prebuilt-themes/indigo-pink.css";
You may also use material design icons in your project, all you have to do just include the below code in your index.html
file.
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
2. Set up Angular CDK Drag and Drop API
The angular/cdk/drag-drop module provides access for creating a drag and drop interface with full flexibility.
The Angular Component Development Kit (CDK) support free dragging, sorting the list, transferring items from the lists, animations, drag handles, place holders, previews and locking along an axis. Now, this is more comfortable and easy with API offered along with the kit.
Install Angular CDK Package for Drag and Drop
npm install @angular/cdk
To work with Angular Drag and Drop, we must import the DragDropModule
service within the app.module.ts
file.
import { DragDropModule } from '@angular/cdk/drag-drop';
@NgModule({
declarations: [...],
imports: [
DragDropModule
],
providers: [...],
bootstrap: [...],
schemas: [...]
})
3. Create Reordering Lists Functionality with Angular Drag and Drop
- The set of items that can be dragged are wrapped in the container where the
cdkDropList
directive is applied. By adding the cdkDropList, you have certain restrictions in dropping the elements. - When the user drops an item in the container, you can see the derivate appearing
cdkDropListDropped
. For instance, the Movie name from the example will call for the function ofdrop($event)
. This event is being called whenever the user drags and drops movie’s name from the movie’s list.
Go to app.component.ts
file and paste the below code.
<div cdkDropList class="example-list" (cdkDropListDropped)="drop($event)">
<div class="example-box" *ngFor="let movieName of Movies" cdkDrag>{{movieName}}</div>
</div>
To make our list look good, we must include the CSS classes within the app.component.css
file.
.wrapper {
margin: 25px auto;
max-width: 600px;
text-align: center;
padding: 0 20px;
}
.container {
width: 45%;
margin: 0 25px 25px 0;
display: inline-block;
vertical-align: top;
}
.movie-list {
width: 80%;
border: solid 1px #ccc;
min-height: 60px;
display: inline-block;
background: white;
border-radius: 4px;
overflow: hidden;
margin-top: 25px;
}
.movie-block {
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);
}
.movie-block:last-child {
border: none;
}
.movie-list.cdk-drop-list-dragging .movie-block:not(.cdk-drag-placeholder) {
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}
I will be calling drop()
method for dragging and dropping HTML element in Angular app. moveItemInArray function is used within the drop() method and, it takes three arguments.
import { Component } from '@angular/core';
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
Movies = [
'Blade Runner',
'Cool Hand Luke',
'Heat',
'Juice',
'The Far Side of the World',
'Morituri',
'Napoleon Dynamite',
'Pulp Fiction'
];
drop(event: CdkDragDrop<string[]>) {
moveItemInArray(this.Movies, event.previousIndex, event.currentIndex);
}
}
4. Transfer Items Between Lists using cdkDropList
With the help of cdkDropList directive, we can drag the item from one drop zone to another dropzone. As you can see we have two blocks, movies list and watched movies list. With the help of Angular drag and drop, we can interchange movies data between both the lists.
As you can see I used 2 arrays one is filled with movies name, and the other one is empty.
Then go to app.component.ts
file and include the following code.
import { Component } from '@angular/core';
import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
// Transfer Items Between Lists
MoviesList = [
'The Far Side of the World',
'Morituri',
'Napoleon Dynamite',
'Pulp Fiction',
'Blade Runner',
'Cool Hand Luke',
'Heat',
'Juice'
];
MoviesWatched = [
];
onDrop(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);
}
}
}
Go to app.component.html
file and paste the below code.
<div class="container">
<h2>Movies</h2>
<div
cdkDropList
#moviesList="cdkDropList"
[cdkDropListData]="MoviesList"
[cdkDropListConnectedTo]="[doneMovieList]"
class="movie-list"
(cdkDropListDropped)="onDrop($event)">
<div class="movie-block" *ngFor="let moviesList of MoviesList" cdkDrag>{{moviesList}}</div>
</div>
</div>
<div class="container">
<h2>Movies Watched</h2>
<div
cdkDropList
#doneMovieList="cdkDropList"
[cdkDropListData]="MoviesWatched"
[cdkDropListConnectedTo]="[moviesList]"
class="movie-list"
(cdkDropListDropped)="onDrop($event)">
<div class="movie-block" *ngFor="let moviesWatched of MoviesWatched" cdkDrag>{{moviesWatched}}</div>
</div>
</div>