Nuxt.jsで並び替え可能なv-data-tableを作ってみる(with vuedraggable & Vuetify & vue-property-decorator)

2020.10.26

はじめに

vuedraggableめっちゃ便利で最高ですね。作ってくれた方本当にありがとうございます。

ただ、Nuxt.jsアプリ(with vue-property-decoratorな環境)にこれを組み込んで、並び替え可能なVuetifyのv-data-tableを作ろうとしたところ少し苦労したところがありました。 解決のために、別なライブラリに切り替えてみたり、クラスを付ける場所を色々と替えてみたり・・・ もしかしたら同じように悩む方がいるかも、ということで色々試した結果動作できたものを記事化したいと思います。

やってみたこと

Vue-Property-decoratorを導入

「Nuxt.jsでTypeScriptを使う(with vue-property-decorator)」の記事を参照

Vuetifyを導入

Nuxt.jsでVuetifyを使う(with vue-property-decorator)の記事を参照

vuedraggableを導入

$ npm i vuedraggable

pageの作成

$ vim pages/table.vue

pages/table.vue

<template>
  <v-container>
    <v-row>
      <v-col>
        <v-data-table :headers="headers" :items="dpt">
          <template v-slot:body="{items}">
            <tbody v-model="dpt" is="draggable" tag="tbody">
              <tr v-for="(item, i) in items" :key="i">
                <td>{{item.id}}</td>
                <td>{{item.name}}</td>
              </tr>
            </tbody>
          </template>
        </v-data-table>
      </v-col>
    </v-row>
    <v-row>
      <v-col>
        <h2>dptオブジェクトの状態</h2>
        <pre>{{ dpt }}</pre>
      </v-col>
    </v-row>
  </v-container>
</template>

<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import draggable from "vuedraggable";

@Component({
  components: { draggable },
})
export default class TablePage extends Vue {
  headers = [
    { text: "ID", value: "id" },
    { text: "部門名", value: "name" },
  ];

  dpt = [
      {
        id: "1",
        name: "事業本部1",
      },
      {
        id: "2",
        name: "事業本部2",
      },
      {
        id: "3",
        name: "事業本部3",
      },
    ];
}
</script>

ポイント

  • v-data-tableコンポーネントを定義します
  • <tr> 要素をドラッグ&ドロップできるようにするために、 v-slot:body (デフォルトのテーブル を置き換えるスロット)を利用します
  • スロット直下に <tbody v-model="dpt" is="draggable" tag="tbody"> の要素を定義します
    • v-model: v-data-tableで利用するモデルオブジェクト名を指定
    • is: draggable を指定(固定)
    • tag: tbody を指定(固定)

動作結果

/table にアクセスしてみると、このような形でテーブルの行が動的に変更できるようになっています!

まとめ

vuedraggableを使って、やりたいことをかなりショートカットできました。 私と同じように悩んでしまった方の参考になれば幸いです。

参考