This page looks best with JavaScript enabled

The Magic of VueDraggable

 ·   ·  ☕ 5 min read

I had used VueDraggable in my projects before, but only sparingly. One of the recent experiences taught me just how cool it was!

The Problem of Drag & Drop

There is no problem.. really.

  1. You drag
  2. You drop
  3. And the world goes “yeah yeah yeah”

(read using this tone - sorry, couldn’t resist)

The problem manifests itself when that drag and drop can include any and all components - so, that’s effectively modern web.

VueDraggable can make that problem go away - in a nice way. You can almost drag any component to any component, and still live to tell that tale. Do remember though - we are not solving problem of dragging external resources (like URLs, images or text ) on to our web app, but rather dealing with the problem of moving or copying a component of our app in “some other” (hopefully happier) place.

Get Started

Add the vuedraggable package to get started.

1
npm i --save vuedraggable

You can now use <draggable> component.

1
2
3
<draggable>
  <!-- almost anything -->
</draggable>

Anything that you want to drag and drop will be contained within draggable. Let’s see examples to understand more.

A Simple Drag & Drop

The beauty of vuedraggable is that you can drag and drop anything. Let’s try out with something simple first - text.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<draggable v-model="items" class="row">
  <v-col
    cols="12"
    v-for="(item, index) in items"
    :key="item.id"
    style="font-weight:bold"
  >
    {{item.title}}
  </v-col>
</draggable>

Write some Javascript..

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
new Vue({
  el: "#app",
  vuetify: new Vuetify(),

  methods: {},
  data: () => ({
    items: [
      { id: 1, title: "abc" },
      { id: 3, title: "ghi" },
      { id: 4, title: "jkl" },
      { id: 5, title: "mno" },
      { id: 2, title: "def" },
    ],
    //
  }),
});

And you are done!

vuedraggable-text

Vuedraggable takes care of identifying the elements, finding their boundaries, and pushing the elements to the right place after the drag & drop.

Drag & drop from one group to the other

Kanban boards are all the rage these days (huh.. kids). How about designing your own Kanban board? Just use Vuedraggable!

See the below example using Vuetify to create the grid and for some basic styling.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<div id="app">
  <v-app>
    <v-container>
      <v-row>
        <v-col cols="3">
          <div style="color:red; font-weight:bold; padding-bottom:30px">Planned</div>
          <draggable v-model="planned" group="kanban" tag="ul">

            <li v-for="item in planned" :key="item.id" style="font-weight:bold;">
              {{item.title}}
            </li>
          </draggable>
        </v-col>
        <v-col cols="3">
          <div style="color:red; font-weight:bold; padding-bottom:30px">In Progress</div>
          <draggable v-model="inprogress" group="kanban" tag="ul">

            <li v-for="item in inprogress" :key="item.id" style="font-weight:bold;">
              {{item.title}}
            </li>
          </draggable>
        </v-col>
        <v-col cols="3">
          <div style="color:red; font-weight:bold; padding-bottom:30px">Done</div>
          <draggable v-model="done" group="kanban" tag="ul">

            <li v-for="item in done" :key="item.id" style="font-weight:bold;">
              {{item.title}}
            </li>
          </draggable>
        </v-col>
    </v-container>

  </v-app>
</div>

Add Javascript..

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
new Vue({
  el: "#app",
  vuetify: new Vuetify(),

  methods: {},
  data: () => ({
    planned: [
      { id: 1, title: "abc" },
      { id: 2, title: "ghi" },
      { id: 3, title: "jkl" },
      { id: 4, title: "mno" },
      { id: 5, title: "def" },
    ],
    inprogress: [
      { id: 6, title: "123" },
      { id: 7, title: "345" },
    ],
    done: [{ id: 8, title: "!@#" }],
    //
  }),
});

You will get to this result in no time..

vuedraggable-text-group

All we did was to specify a group name that should remain the same for all elements in the same group.

Also, did you take note that I used a different tag here?

1
<draggable v-model="inprogress" group="kanban" tag="ul"></draggable>

You can specify any tag to wrap around your draggable elements using tag, it is div by default. Take care to see that the draggable elements (the elements with for loop) are direct descendants of <draggable> element.

Try it out on Codepen.

Drag & drop images

How about dragging and dropping images?

vuedraggable-images

Images are just as easy as text.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<v-container>
  <draggable v-model="items" class="row">
    <v-col cols="12" sm="4" v-for="item in items" :key="item.id" class=".item">
      <v-card class="mt-2 mb-2 item" color="grey lighten-4" flat>
        <v-toolbar flat dense color="transparent" class="font-weight-bold">
          {{item.title}}
        </v-toolbar>
        <v-img :src="item.img" height="300px"></v-img>
      </v-card>
    </v-col> </draggable
></v-container>

Here’s the Codepen.

How about alternatives?

VueDraggable is based on sortable library and is fairly well documented and quite popular. You should be in safe hands for the most part. There are other libraries like -

However, do note a limitation of sortablejs (and VueDraggable) - it makes use of native HTML5 API for drag & drop and is subject to its constraints. You will notice this if you need to take control of every event or enable advanced functions during drag & drop.

To go beyond HTML5 API, have a look at one of the alternatives below.

  • vue-grid-layout: Certainly one of the more powerful libraries for drag & drop. Quite powerful, actively maintained and it just rocks
  • vue-easy-dnd: This library is fairly new but gaining rapid popularity
  • Vue-smooth-dnd: offers more functionality, not constrained by HTML5 API

While the above libraries are powerful, they also need quite a bit more coding to get things going. For example, vue-grid-layout needs the exact points in x/y-axes, and element height/width.

Finis

VueDraggable is a super-friendly, and easy-to-use library. You can do much much more with VueDraggable like cloning elements, drag & drop nested elements.

See more examples of what VueDraggable can do. Use it in your own projects and go crazy!

Stay in touch!
Share on

Prashanth Krishnamurthy
WRITTEN BY
Prashanth Krishnamurthy
Technologist | Creator of Things