b-tableを用いてドラッグ&ドロップで順番変更可能なテーブル【BootstrapVue】

スポンサーリンク

はじめに

今回は、BootstrapVueのb-tableで、ドラッグアンドロップで表内のデータ順を変更できるvueプログラムを作成しました。発端としては、b-tableでドラッグアンドドロップが行える情報がなく、ほとんどにおいてb-table-simpleを使用するものであったためです。

コード作成

b-tableを作成します。BootstrapVueにあるセオリー通りにfieldsitemsをpropsに定義します。今回は、ドラッグアンドドロップを使うためtbody-tr-attrにHTMLでドラッグアンドドロップをサポートするdraggableにtrueを渡します。

 <b-table
    :fields="fields"
    :items="items"
    :tbody-tr-attr="{draggable: true}"
    striped
  />

ただしこのままではdraggableのemitを検知ことができませんので、addEventListenerを用いてイベントを検知します。今回はtrをすべて探します。そのため、indexとして渡すものはタイトルヘッダを覗いたものになりますので、index-1を実施します。

const trs = document.querySelectorAll("tr");
  trs.forEach((tr, index) => {
    if(index === 0) return;
    tr.addEventListener("dragstart", () => this.onDragStart(index - 1));
    tr.addEventListener("dragover", (event) => event.preventDefault());
    tr.addEventListener("drop", () => this.onDrop(index - 1));
  });

最後に、addEventListenerにて受け取ったイベントを処理するため、methodsに各関数を定義します。上記の場合だとonDragStartonDropが必要になります。

onDragStartではドラッグ開始位置の保持、onDropでは実際のデータ移動を行います。

methods: {
  /** ドラッグ開始時の処理 */
  onDragStart(index) {
    this.beforeIndex = index;
  },
  /** ドラッグ完了後の処理 */
  onDrop(index) {
    const item = this.items.splice(this.beforeIndex, 1)[0];
    this.items.splice(index, 0, item);
  },
},

最後に、実際に作成したコードを提示していきます。特に親コンポーネントなどは考慮していないため、fieldsitemsはベタ打ちしています。

<template>
  <b-table
    :fields="fields"
    :items="items"
    :tbody-tr-attr="{draggable: true}"
    striped
  />
</template>

<script>
export default {
  name: "draggableTable",
  mounted() {
    const trs = document.querySelectorAll("tr");
    trs.forEach((tr, index) => {
      if(index === 0) return;
      tr.addEventListener("dragstart", () => this.onDragStart(index - 1));
      tr.addEventListener("dragover", (event) => event.preventDefault());
      tr.addEventListener("drop", () => this.onDrop(index - 1));
    });
  },
  data() {
    return {
      beforeIndex: 0,
      items: [
        {name: "安倍", age: "22", section:"技術部"},
        {name: "伊野", age: "34", section:"人事部"},
        {name: "宇野", age: "36", section:"人事部"},
      ],
    };
  },
  computed: {
    fields() {
      return [
        {key: "name", label: "名前"},
        {key: "age", label: "年齢"},
        {key: "section", label: "部署"},
      ];
    },
  },
  methods: {
    /** ドラッグ開始時の処理 */
    onDragStart(index) {
      this.beforeIndex = index;
    },
    /** ドラッグ完了後の処理 */
    onDrop(index) {
      const item = this.items.splice(this.beforeIndex, 1)[0];
      this.items.splice(index, 0, item);
    },
  },
};
</script>

これでb-tableを用いたドラッグアンドドロップが実装できました。b-tableは非常に使い勝手が良いためこれで実装できると非常に助かります。

なお、BootstrapVueのissueを漁っていましたがコードの膨大化に伴いb-tableでのdraggableの実装は今のところ予定されていないようです。

コメント

タイトルとURLをコピーしました