[Vuejs]-How pass result sortablejs to vue data?

4👍

I stumbled upon such a task in one of my projects. I know that there are many similar solutions here on stackoverflow, but they didn’t work in my case. The thing was that no one tells you need to provide Sortable-object with dataIdAttr property and set a proper attribute in children of sortable-dom-element. At least you need to do it working with bootstrap-vue table. That will help to resort rows backwards and reset vue-reactive-data according to changed drag indexes.

I hope that will be useful for someone.

<template>
    <b-table
        v-draggable-rows="{ data: items, orderColumn: '№' }"
        :items="items"
    >
        <template #cell(Dragger)>
            <IconDragHandle />
        </template>
    </b-table>
</template>

<script>
import IconDragHandle from '~/components/icons/table/IconDragHandle.vue';

export default {
  components: {
    IconDragHandle,
  },

  data() {
    return {
      items: [],
    };
  },

  created() {
    this.items = [...Array(8).keys()].map(x => ({
      'Dragger': '',
      '№': x + 1,
      'Cell1': x + 1,
      'Cell2': x + 1,
      'Cell3': x + 1,
    }));
  },
};
</script>
import Vue from 'vue';
import Sortable from 'sortablejs';

Vue.directive('draggable-rows', {
  bind(el, binding, vnode) {
    const table = el;
    table._sortable = createSortable(
      table.querySelector('tbody'),
      binding.value,
      vnode
    );
  },
});

const createSortable = (el, options, vnode) => {
  let order = [];
  const data = options.data;
  const orderColumn = options.orderColumn;
  for (let i = 0; i < el.children.length; i++) {
    el.children[i].setAttribute('sortable-id', i);
  }
  return Sortable.create(el, {
    dataIdAttr: 'sortable-id', // default: data-id
    animation: 150,
    easing: 'cubic-bezier(0.25, 1, 0.5, 1)',
    handle: '.custom-table-draggable-handle',
    ghostClass: 'custom-draggable-rows-ghost',
    chosenClass: 'custom-draggable-rows-chosen',
    dragClass: 'custom-draggable-rows-drag',

    onStart() {
      order = [...this.toArray()];
    },

    onEnd(evt) {
      this.sort(order);
      data.splice(evt.newIndex, 0, ...data.splice(evt.oldIndex, 1));
      if (!orderColumn) return;
      data.forEach((o, i) => {
        o[orderColumn] = i + 1;
      });
    },
  });
};

Draggable Draggable.Vue Bootstrap-Vue SortableJS v-sortable Reorder

👤kelken

Leave a comment