search
LoginSignup
16
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

Angular v7のDragDropModuleを使ってTrelloっぽいの作ってみた

Angular 7.0.0がリリースされましたね 🎉
CDKにDrag and DropのModuleが追加されたので触ってみました。

ドラッグ・アンド・ドロップの機能って自前で開発すると結構めんどくさかったのが、めちゃくちゃ簡単に実装できました👏楽しい👏
DEMO

やったこと

  • app.module.tsDragDropModule をimportする
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { DragDropModule } from '@angular/cdk/drag-drop';

import { AppComponent } from './app.component';

@NgModule({
  imports: [
    BrowserModule,
    DragDropModule
  ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }
  • app.component.tsCdkDragDrop, moveItemInArray, transferArrayItem をimportする
  • ドロップ時のメソッドを定義する
    • event発生したときに、 container が移動前と同じ配列か違う配列かを判定して、 moveItemInArray()transferArrayItem() を実行する
app.component.ts
import { Component } from '@angular/core';
import { 
  CdkDragDrop, 
  moveItemInArray, 
  transferArrayItem 
} from '@angular/cdk/drag-drop';


@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  public todo = [
    '働く',
    '映画を見る',
    '掃除する',
    '洗濯する',
    '飲みに行く',
    '買い物に行く',
    '家に帰る',
    '散歩する',
  ]

  public doing = [
    'サッカーする',
    '野球する',
    'バスケする',
    'テニスする',
  ]

  public done = [
    '本を読む',
    '歯を磨く',
    '昼寝する',
    'メールチェック',
    '犬と遊ぶ'
  ]

  public drop(event: CdkDragDrop<string[]>): void {
    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);
    }
  }
}
  • cdkDropListcdkDrag 要素セットの親要素に追加する
  • #todoList="cdkDropList" ←のように cdkDropListへの参照をテンプレート変数化する
  • [cdkDropListConnectedTo]="[doneList]"
    • 移動先としてつなぎたい cdkDropList の参照を指定する
  • cdkDropListDropped イベントは、ドラッグが終了した時に発火するので、 app.component.ts で定義しておいた drop() メソッドを使う
app.component.html
<section class="container">
  <h1>MY TASKS</h1>
  <div class="cards">
    <section class="card">
      <h2>
        TODO
      </h2>
      <ul cdkDropList 
          #todoList="cdkDropList"
          [cdkDropListData]="todo"
          [cdkDropListConnectedTo]="[doingList, doneList]"
          class="list"
          (cdkDropListDropped)="drop($event)">
        <li class="item" *ngFor="let item of todo" cdkDrag>{{item}}</li>
      </ul>
    </section>
    <section class="card">
      <h2>
        DOING
      </h2>
      <ul cdkDropList 
          #doingList="cdkDropList"
          [cdkDropListData]="doing"
          [cdkDropListConnectedTo]="[todoList, doneList]"
          class="list"
          (cdkDropListDropped)="drop($event)">
        <li class="item" *ngFor="let item of doing" cdkDrag>{{item}}</li>
      </ul>
    </section>
    <section class="card">
      <h2>
        DONE
      </h2>
      <ul cdkDropList 
          #doneList="cdkDropList"
          [cdkDropListData]="done"
          [cdkDropListConnectedTo]="[todoList, doingList]"
          class="list"
          (cdkDropListDropped)="drop($event)">
        <li class="item" *ngFor="let item of done" cdkDrag>{{item}}</li>
      </ul>
    </section>
  </div>
</section>

さいごに

実際の機能開発だと、もっとやることあると思いますが、とりあえずUIはこれだけで実装できました。
ライブラリとか使ったり、自前で開発する必要がなさそうなので、とても良いですね。

cf.

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
16
Help us understand the problem. What are the problem?