LoginSignup
0
0

More than 1 year has passed since last update.

【Vue3】vue.draggable の中で vue.draggable を使う(elementやindexに別名をつけられる)

Posted at

Vue2からのマイグレーションで躓く

vue.draggableをドキュメントに記載があるとおりにマイグレーションしていくと、以下のようになる。

<!-- vue 2 version -->
<draggable v-model="myArray">
  <div v-for="element in myArray" :key="element.id">{{element.id}}. {{element.name}}</div>
</draggable>
<!-- vue 3 version -->
<draggable v-model="myArray" item-key="id">
  <template #item="{element}">
    <div>{{element.id}}. {{element.name}}</div>
  </template>
</draggable>

vue.draggableの中でvue.draggableを利用している場合はどうするんだろう?

例えば2階層のオブジェクト配列があり、それぞれを並び替えられるようにしたい場合、Vue2で以下のようになる。

// 2階層のオブジェクト配列
const myArray = [
  {
    id: 1,
    name: "parent1",
    childArray: [
      {
         id: 1,
         name: "child1",
      },
      {
         id: 2,
         name: "child2",
      }
    ] 
  },
  {
    id: 2,
    name: "parent2",
    childArray: [
      {
         id: 3,
         name: "child3",
      },
      {
         id: 4,
         name: "child4",
      }
    ] 
  },
]
<!-- vue 2 version -->
<draggable v-model="myArray">
  <div v-for="element in myArray" :key="element.id">
    <div>{{element.id}}. {{element.name}}</div>
    <draggable v-model="element.childArray">
      <div v-for="element2 in element.childArray" :key="element2.id">{{element2.name}}</div>
    </draggable>
  </div>
</draggable>

しかし、ここで問題になるのが、Vue3ではelementを別の名前にするとエラーになってしまうこと。

<!-- vue 3 version -->
<draggable v-model="myArray" item-key="id">
  <template #item="{row}">
    <div>{{row.id}}. {{row.name}}</div>
  </template>
</draggable>

// TypeError: Cannot read properties of undefined (reading 'id')

ドキュメントだけを見るとここで詰んでしまい、子要素用のコンポーネントを別途作成することを考えなければならない気がするが、いちいち値を双方向に受け渡す必要が出てきてしまい、ちょっと面倒くさい。

っていうか、ループ変数が必ずelementになるってひどくない?

arrayならrowとか、peoples なら people にして視認性を確保できないものか。

マニュアルに書いていないけど別名をつけることができた

<!-- vue 3 version -->
<draggable v-model="myArray" item-key="id">
  <template #item="{element}">
    <div>
      <div>{{element.id}}. {{element.name}}</div>
      <draggable v-model="element.myArray" item-key="id">
        <template #item="{element: element2}">
          <div>{{element2.id}}. {{element2.name}}</div>
        </template>
      </draggable>
  </template>
</draggable>

{element: 別名} とすることで今まで通り利用できるようになった。
これはindexにも利用可能で、{element: row, index: idx1} などといった設定が可能。
フォームだとID属性つけたり、引数付きcomputedでゴニョゴニョするのにindexを利用することも多いので、ここも任意の変数にできないと困るので非常に助かる。

<!-- vue 3 version -->
<!-- 視認性アップ -->
<draggable v-model="myArray" item-key="id">
  <template #item="{element: parentRow, index: idx1}">
    <div>
      <div>{{ idx1 + 1 }}行目: {{parentRow.id}}. {{parentRow.name}}</div>
      <draggable v-model="parentRow.myArray" item-key="id">
        <template #item="{element: childRow, index: idx2}">
          <div>{{ idx1 + 1 }}行目の{{ idx2 + 1 }}個目: {{childRow.id}}. {{childRow.name}}</div>
        </template>
      </draggable>
  </template>
</draggable>

参考資料

この使い方は唯一、Issueにてこの方法を見つけることができた。
ちゃんとドキュメントに書いておいてほしい・・・vue.draggableのマイグレーションで躓いている人、多いと思うんだ・・・
https://github.com/SortableJS/vue.draggable.next/issues/165

0
0
0

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
  3. You can use dark theme
What you can do with signing up
0
0