🍱 CDK Drag and Drop
Add drag and drop capabilities to a Material Card
Use the Angular CDK Drag and Drop Module to enable reordering of Kanban boards and tasks.
Steps
Step 1 - Initial Setup
command line
ng g c kanban/board-list
ng g c kanban/board
Point the kanban router to the board list
kanban-routing.module.ts
import { BoardListComponent } from './board-list/board-list.component';
const routes: Routes = [
{ path: '', component: BoardListComponent }
];
Step 2 - Board List
board-list.component.ts
import { Component, OnInit, OnDestroy } from '@angular/core';
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
import { Subscription } from 'rxjs';
import { Board } from '../board.model';
import { BoardService } from '../board.service';
@Component({
selector: 'app-board-list',
templateUrl: './board-list.component.html',
styleUrls: ['./board-list.component.scss']
})
export class BoardListComponent implements OnInit, OnDestroy {
boards: Board[];
sub: Subscription;
constructor(public boardService: BoardService) {}
ngOnInit() {
this.sub = this.boardService
.getUserBoards()
.subscribe(boards => (this.boards = boards));
}
ngOnDestroy() {
this.sub.unsubscribe();
}
drop(event: CdkDragDrop<string[]>) {
moveItemInArray(this.boards, event.previousIndex, event.currentIndex);
this.boardService.sortBoards(this.boards);
}
}
board-list.component.html
<div
cdkDropList
cdkDropListOrientation="horizontal"
class="boards"
(cdkDropListDropped)="drop($event)"
>
<app-board cdkDrag *ngFor="let board of boards" [board]="board">
<mat-icon cdkDragHandle class="handle">drag_indicator</mat-icon>
</app-board>
<div class="board-button">
<button
mat-raised-button
color="accent"
cdkDragDisabled
>
New Board
</button>
</div>
</div>
Step 2 - Board
board.component.ts
import { Component, Input } from '@angular/core';
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
import { BoardService } from '../board.service';
@Component({
selector: 'app-board',
templateUrl: './board.component.html',
styleUrls: ['./board.component.scss']
})
export class BoardComponent {
@Input() board;
constructor(private boardService: BoardService) {}
taskDrop(event: CdkDragDrop<string[]>) {
moveItemInArray(this.board.tasks, event.previousIndex, event.currentIndex);
this.boardService.updateTasks(this.board.id, this.board.tasks);
}
}
board.component.html
<mat-card class="outer-card">
<mat-card-header>
<!-- Slot for the handle -->
<ng-content></ng-content>
<mat-card-title>
{{ board.title }}
</mat-card-title>
<mat-card-subtitle>
{{ board.id }}
</mat-card-subtitle>
</mat-card-header>
<div
class="tasks"
cdkDropList
cdkDropListOrientation="vertical"
(cdkDropListDropped)="taskDrop($event)"
>
<div
class="inner-card"
cdkDrag
*ngFor="let task of board.tasks; let i = index"
>
<mat-card [ngClass]="task.label"> {{ task.description }} </mat-card>
</div>
</div>
</mat-card>