はじめに
この記事はAngular Advent Calendar 2018の8日目の記事です
Angular7がリリースされてComponentDevKitにDragAndDropが入ってきました
ということで簡単なTODOアプリを作ってみます
CDKとは
簡単に言うと一般的なWebアプリケーションで使うUIを提供してくれるライブラリ群です
少ないコード記述量・短時間で必要な機能を構築できます
Angular公式が作っているので安心感がありますね
動作環境
$ npx ng --version
_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
Angular CLI: 7.0.2
Node: 9.3.0
OS: linux x64
Angular: 7.0.0
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router
Package Version
-----------------------------------------------------------
@angular-devkit/architect 0.10.2
@angular-devkit/build-angular 0.10.2
@angular-devkit/build-optimizer 0.10.2
@angular-devkit/build-webpack 0.10.2
@angular-devkit/core 7.0.2
@angular-devkit/schematics 7.0.2
@angular/cdk 7.0.1
@angular/cli 7.0.2
@angular/material 7.0.1
@ngtools/webpack 7.0.2
@schematics/angular 7.0.2
@schematics/update 0.10.2
rxjs 6.3.3
typescript 3.1.3
webpack 4.19.1
install,project作成
cliでnewすると対話形式でいくつか質問される(7から)ので答えます
$ npx ng add @angular/cdk
$ npx ng add @angular/material
+ @angular/material@7.0.1
added 68 packages in 14.639s
Installed packages for tooling via npm.
? Enter a prebuilt theme name, or "custom" for a custom theme: indigo-pink
? Set up HammerJS for gesture recognition? Yes
? Set up browser animations for Angular Material? Yes
materialの雛形追加
とりあえずナビだけ
npx ng g @angular/material:material-nav --name side-nav
サーバ起動
npx ng s
実装
準備が整ったのでTODOリストを作っていきます
ドキュメントは下記
Drag and Drop | Angular Material
[https://material.angular.io/cdk/drag-drop/overview:embed:cite]
サンプルにすでにそれっぽく動かせるコードがあるのでそこからすこし手を加えてTODOリストを作ってみます
- サンプル
Drag&Drop connected sorting - StackBlitz
[https://stackblitz.com/angular/mrlygxvavkm?file=app%2Fcdk-drag-drop-connected-sorting-example.ts:embed:cite]
- テンプレート側
#todoList="cdkDropList"
でテンプレート変数にディレクティブのインスタンスを代入
[cdkDropListConnecedTo]="[doneList]"
でどの箱とつながっているかを定義
配列になっているので複数記述できる感じですね
サンプルだと箱が2つなのでもう片方の箱のインスタンスを指定しています
[cdkDropListData]="todo"
で対象の箱の初期データを渡しています
データの内容はtsファイルの方に記述されています
(cdkDropListDropped)
cdkDropList
配下のcdkDrag
の要素に対するドラッグが終わったらイベントを受け取るようになっています
drop
関数では対象のタスクが同じ箱内で順番だけが変わった場合はmoveItemInArray
別の箱へ移動した場合はtransferArrayItem
を呼び出してそれぞれ適切なデータをとってきて移動させています
めちゃくちゃわかりやすい!
今回はこのサンプルに下記追加してみます
- doingのリスト
- タスクの追加機能
- タスクの削除機能
doingのリスト
-
他2つの箱にならって箱を追加
-
各箱の
cdkDropListConnecedTo
を3つ相互に接続させるように修正
これだけですね
データの追加
テキストフィールドを用意してクリックイベントで対象データ(todo)に追加するだけ
- todo-list.component.ts
addTask(task: string): void {
this.todo.push(task);
}
- todo-list.component.html
<mat-form-field class="example-full-width">
<input #task matInput placeholder="Task" value="task">
</mat-form-field>
<button mat-stroked-button color="primary" (click)="addTask(task.value)">Add</button>
あとはAngular側がよしなにやってくれます
データの削除
こちらも対象のデータから削除するだけ
- todo-list.component.ts
deleteTask(data: any[], index: number): void {
data.splice(index,1);
}
- todo-list.component.html
<div class="example-box" *ngFor="let item of doing; let i=index" cdkDrag>
{{item}}
<button mat-icon-button color="warn" (click)="deleteTask(doing,i)">
<mat-icon aria-label="Example icon-button with a heart icon">
delete
</mat-icon>
</button>
</div>
最終的にこんな感じになりました
まとめ
なんて楽なんだ!という印象でした
ドラッグアンドドロップのUIは1から実装ってなるとちょっと気が重くなる感じのイメージだったのですがCDKを使って実装すれば簡単に実装できそうです
これ使って自分用にTODO作るか!っていうくらい簡単でした
CDKは他にも色々機能があるので調べて使ってみたいと思います
今後さらに増えてくれることに期待してます
今回使ったサンプルのコードは下記に置きました
swfz/todo-sample: angular todo list
[https://github.com/swfz/todo-sample:embed:cite]