samwalpole.com

5 min read

Build an interactive kanban board with Vue Draggable

Vue Draggable is a great library for Vue.js that makes it super simple to create interactive draggable components with virtually no effort. I have recently used it to create an interactive kanban board, in which tasks can be rearranged and moved between cards just by dragging.

Preview

So let's start by creating some reorderable cards! P.S I'm using Vuetify as the UI framework, in case the tags look unfamiliar.

<template>
  <v-container fluid>
    <v-row>
      <v-col class="text-right">
        <v-btn color="primary" depressed @click="addCard"> Add Card </v-btn>
      </v-col>
    </v-row>
    <v-row>
      <v-col v-for="(card, i) in cards" :key="i" cols="12" sm="6" md="4">
        <v-card outlined>
          <v-card-title>
            <v-text-field v-model="card.title"></v-text-field>
          </v-card-title>
        </v-card>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
export default {
  data: () => ({
    cards: []
  }),  
  methods: {
    addCard() {
      const card = {
        title: 'New Card',
        tasks: [],
      }

      this.cards.push(card)
    },
  }
}
</script>

The code above should give you the ability to create cards by clicking the Add Card button, but they aren't draggable yet. First make sure that you have VueDraggable installed by running:

yarn add vuedraggable

Then import VueDraggable into you component:

<script>
import Draggable from 'vuedraggable'

export default {
  components: {
    Draggable,
  },
  data: () => ({
    cards: []
  }),  
...

Finally, all we need to do to make the cards draggable is to wrap the cards with the draggable component. In our case, we're replacing v-row with draggable.

<draggable :list="cards" group="cards" class="row">
  <v-col v-for="(card, i) in cards" :key="i" cols="12" sm="6" md="4">
...

There are two attributes that are important to note. First, the list attribute defines the list of objects that should be draggable, in our case the cards array. Secondly, the group attribute is just a way of identifying groups of draggable components (you'll see why this is useful when we move on to creating draggable tasks).

Try running your project now. You should be able to create multiple cards, and reorder them by dragging!

Now let's move on to the tasks. Below the v-card-title tag we need to add the following code:

<v-card-text>
  <draggable :list="card.tasks" group="tasks" class="row">
    <v-col v-for="(task, j) in card.tasks" :key="j" cols="12">
      <v-text-field v-model="task.title">
        <template v-slot:append>
           <v-btn color="error" text class="ml-3" @click="deleteTask(i, j)"> Delete </v-btn>
        </template>
      </v-text-field>
    </v-col>

    <template v-slot:footer>
      <v-col cols="12">
        <v-btn color="primary" depressed block @click="addTask(card)"> Add Activity </v-btn>
      </v-col>
      <v-col cols="12">
        <v-btn color="error" text block @click="deleteCard(i)"> Delete Card </v-btn>
      </v-col>
    </template>
  </draggable>
  </v-card-text>

Add the following in the script section:

methods: {
    deleteCard(index) {
      this.cards = [...this.cards.slice(0, index), ...this.cards.slice(index + 1)]
    },
    addTask(card) {
      const task = {
        title: 'New Activity'
      }

      card.tasks.push(task)
    },
    deleteTask(cardIndex, taskIndex) {
      const card = this.cards[cardIndex]
      card.tasks = [...card.tasks.slice(0, taskIndex), ...card.tasks.slice(taskIndex + 1)]
    }
}

Here we've added the ability to add and delete tasks from each card, as well as delete the card itself. We've also added another draggable component, which wraps around each group of tasks. We've given it a group name of tasks. This is important because each list of tasks will have the same group name, meaning that we can drag tasks from one card to another! P.S. if you only wanted tasks to be reorderable within its own card, you would have to create a unique group name for each list of tasks.

And that's it! Hopefully this post has shown you how quick and easy it is to develop highly interactive draggable apps using the Vue Draggable library. What ideas will you use it for?

Conclusion

In this post I have shown you the basics of using the Vue Draggable library to create an interactive kanban board. The full repository can be found here on GitHub.