🍱 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

file_type_ng_component_ts kanban-routing.module.ts
import { BoardListComponent } from './board-list/board-list.component';


const routes: Routes = [
  { path: '', component: BoardListComponent }
];

Step 2 - Board List

file_type_ng_component_ts 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);
  }

}
file_type_html 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

file_type_ng_component_ts 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);
  }
}
file_type_html 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>

Questions? Let's chat

Open Discord