活動報告7 d&dなディレクティブを作る-
TRANSCRIPT
パソコン部活動報告2015/05/30
最新の技術をとりあえず試してみることを目的とした部です。
2015/05月活動内容
1. angular.js1.3系を利用して再利用可能なディレクティブを作成するその③
Look at me mom...dad and I are having so much fun!
1.概要
1.今回作る予定のディレクティブ
スマホでは使わないと思うけど、タブレットでは Drag&Drop操作はありだと思う。
なので、汎用性のある Drag&Dropディレクティブができれば、 UIのバリエーションを増やせるなーと思い外国産のディレクティブを使ってみたけど一部動作しなかったり拡張しようとしたけどちょっとレベルが足りなかった。
でも Drag&Dropって実際使うと使いにくかったりするよね。結局はエンジニアの自己満足な気がしてきた。
というわけで、作ればいい!という結論に至ったのでつくってみます。
余談ですが、単一画面内で Drag&Dropのソート機能とかだけを使うパターンの場合は JQueryのsortableでやればいいと思う。
1.概要
● Drag元と Drag先をそれぞれ指定するディレクティブ● Drop後はイベントを送出させる● リピートされた要素でも Drag&Dropできるようにする● HTML5の Drag&Dropを使う
機能
ぶっちゃけ t○elloみたいな UIを自分でも実装できるようになりたかったのでこんな感じの機能にしてみた。t○ello使ってみたけど、使いやすいなーって思いました。(別に宣伝じゃないよ)
最近のタスク管理アプリはカードベースの UIが多い気がする。
この UIができると、アジャイル開発用の redmine的なもの作れる気がする。ストーリーをカードにして、順番を定義させて~的なやつ。
2.ディレクティブを考える
1.ディレクティブの構成Drag可能なエリアを指定させるタイプのディレクティブと Drop先であるディレクティブを指定するディレクティブの 2つが必要になる。それぞれのパラメータとかを考えてみた。
restrict: 'AE'transclude: falserequire: '^ngModel'scope: {dragindex: '='}
restrict: 'A'require: '^ngModel'scope: {}
Drag Drop
transcludeを Drag側に指定してみた。これはディレクティブとした要素の内容をテンプレートの一部として利用できるようになるディレクティブ。
後は、 requireを「 require: '^ngModel'」ってする。親コントローラーを参照できるようにして、そこから Dragと Dropされた値を書き換えるためね。
dragIndexは位置を特定するのに使う予定。
2.ディレクティブを考えるリピート要素に対して指定されるディレクティブを想定しているので考え始めるといろいろでてきた。
● Drag中に値を保持させたり、 Dropした時にどこに落ちたかわからないといけなよね。● ってことは、 Dragディレクティブと Dropディレクティブで値を共有しておかなきゃいけないよね。
● Drop後は Drag先から要素を消したいよね● このディレクティブを使う側はそこらへんは意識しないで使いたいよね。
ってことで値の受け渡しとかは SharedServicesにすればよくね?あとはどのタイミングで入れるよ?ってことなんだけど、 を Drag要素、 をエリアとした場合 Drag&Dropでは、①~⑥のアクションが起こるよね。それぞれでイベントが発生してるわけなんだけど、そのイベントを利用すればいけそう。
Dragする Drag中 Dropする
① ② ③Dropエリアに入る ④
dragstart
dragenter
dragover
Drop先を選ぶ
drop
⑤
Drag対象を設定
dropされる可能性があるから dropを特定するための classを設定
位置を設定 Drag対象を取得し
て Drop先に設定して削除
Dropエリアから出る
dragenter時に設定したclassを削除
dragleave
⑥
2.ディレクティブを考えるSharedServicesを作ってみた。
orverIndexは dragoverを出してる要素に指定されたindexを格納する変数。
fromDataは dragされた要素を生成する際に使用したscopeの値を保持する変数。
2.ディレクティブを考える
dragディレクティブを作ってみた。
SharedServicesをインジェクションして使えるようにしたのがこれまでと違うところかな。
linkで要素に draggableを追加して Drag可能にして、分離スコープの dragindexを data-indexとして追加する。
dragstartを onしておいて、イベント発生時に対象要素に指定した data-indexと htmlを取得しておいてdataTransferにぶっこむ。イベント発生した scopeにバインドされた値を SharedServicesの fromに設定。
2.ディレクティブを考える
dropディレクティブを作ってみた。
まずはdragenter,dragover,dragleaveのイベントの処理から。
dragenterと dragleaveに関してはイベントが発生した要素にイベント用の classを追加 /削除しているだけ。
dragoverはイベントが発生した要素から位置を特定するためのindexが存在している( drag要素としても指定されている)かをチェックして indexがあればそれを設定。なかったら特に指定しない。これなら一方的に Dropするエリアであっても対応できる気がする。
2.ディレクティブを考えるdropイベント時の処理。
2.ディレクティブを考えるここの処理では dataTransferと SharedSearviceからデータを取得して、 $modelValueの値を変更することで画面側でも反映されるようにしてる。
後は必要そうな情報を objectにまとめて $emitするって感じ。
一応今は Drop先 (to)、 Drag元 (from)、削除対象 (remove)、同一要素内での移動かのフラグ(isSameContainer)を渡してる。
利用する側は「 dropItemComplete」を onしておいてイベントをキャッチする感じかな。
キャッチしたら、 socket.ioで emitして別の人の画面も反映させにいけば、比較的リアルタイムな感じで行ける気がする。
3.ディレクティブを使う
1. HTMLに指定する
赤枠のところが指定した箇所ね。
3.ディレクティブを使う
うごかすぜー!!!!!!!!
3.ディレクティブを使う
4 .最後
Drop先の要素が 1つしない場合に、一番下に入れれないバグがあるけど、とりあえず動くのが作れた。たぶん、 indexの取得部分にバグがあるのかなー。まぁそのうち直します。今回のディレクティブ作成は結構勉強になったなー。
socket.ioもふつうに使えたから、やれることのバリエーションが増えたかなー。次は Reactやるか、それとも Unity5やるか、どっちにしようかな。