2020
01/28

Vue.Draggableで入力フォームを持ったツリー構造の作り方

ドラッグ&ドロップが可能なツリー状のインターフェイスをつくるためにVue.Draggableを使いましたが、結構手間取ってしまったので備忘録的に使い方をまとめました。

Vue.Draggable

目一杯シンプルにした例です。

サンプル
Github

ADs

親コンポーネント

単にドラッグできるツリー表示だけなら<draggable>で挟むだけなのですが、組み換えや入力などの編集がされたデータを保持するためにコンポーネント化する必要があります。

<draggable>コンポーネントを含めたコンポーネントを作成します(ここでは<tree>がそれにあたります)。
そのtreeコンポーネントにv-modelで使いたいデータを指定します。

なお、datasデータは以下のようになっています。
入力が伴う場合、入力値はこのdatasデータに含めることがポイントです。

tree.vue

ネストされたツリー構造を実現するために、treeコンポーネント内部で自分を呼び出す再帰構造となります。

必ず指定しなければならない属性がいくつかあるので漏れなく指定します。

・:listと:value
属性名は「list/value」で固定です。
ネストされたときに子階層のツリーデータが入ります。
ツリーデータはlist/valueのどちらかに入るので次に続くv-forではcomputedにより存在するものどちらかを使うように指定します(realValueが該当する)。

・@input=”emitter”
親コンポーネントに編集されたデータを渡すために必要です。
methodsで関数の定義も忘れずに行います。

・:group
この属性でnameを定義することで親子階層のドラッグができます。
逆にいうと:group属性の指定がない場合、兄弟関係はドラッグで変更できますが親子を組み替えることができません。

・入力値(フォーム類)
v-for内でv-modelで指定することで、親コンポーネントのdatasに編集内容が反映されます。

・子コンポーネント(tree-child)
tree-childコンポーネントは自分自身を指します。
:listで子に当たるツリーデータを指定します。

サンプルの右側がdatasをJSON.stringifyで出力していますが、ドラッグによる順番変更や入力内容が即時に反映されているのが分かります。

あとはこのdatasを保存したり外部に送信したり違うツリーを作ったり、と使い回してWebアプリケーションを構築していきます。

ハマりどころ

入力値は子コンポーネントのdataで持ってはいけない

入力データはtree.vuedataで持ちたくなりますが、子コンポーネントはネストされるためここでデータを持ってしまうと取得ができなくなります(できるかもしれないがとてもめんどくさそう)。

まとめ

実際に業務で使ったときは手こずってしまいましたが、整理するとシンプルなコードで実装できました。
なぜあんなに時間がかかってしまったのか…。

ドラッグ&ドロップのインターフェイスは一見すごそうでやりたがる方も多いのですが、実際使ってみるとどうなんだろう…というのが正直なところです。

ADs

Post Comments

メールアドレスが公開されることはありません。

Comments

コメントはまだありません。