How to build a Drag&Drop Images Vue.js component from scratch

5 min read

In this post I’m going to dive a bit creating a Vue.js component from scratch using Vue CLI and ES6 to allow users drag&drop images in the browser.

The final implementation is not meant to be “ready to be drop” components for your app. They are better a starting point to be include in your app by adding further logics required by your product.

The component can be used in any Vue app such this one:

<template>
  <div id="app">
      <DropAnImage />
  </div>
</template>

<script>
import DropAnImage from './components/DropAnImage.vue'

export default {
  name: 'app',
  components: {
    DropAnImage
  }
}
</script>


<style>
html, body, #app{
  width:100%;
  height:100%;
  padding: 0;
  margin: 0;
  overflow: hidden;
}
</style>

And here up and running, if you want to drop something:

Just to be clear, the above app is not uploading anything, all happens client-side only.

Build the component #

There are two relevant parts to make it work properly:

  • the native drag events
  • the FileReader object to read on-the-fly dropped elements

The native events #

The browser allows to listen for dragover, dragleave and drop events to performe the interactive part of the component.

In Vue.js we can set those event in the template:

<template>
  <div class="drop" 
    @dragover.prevent="dragOver" 
    @dragleave.prevent="dragLeave"
    @drop.prevent="drop($event)">

  </div>
</template>

With this events you can define some logic to display relevant UI information for the user. The drop event is the one that bring to the next part.

The FileReader #

The FileReader allows to read the content of a file attached to an event. It requires a File object to work properly.

This is the typical implementation:

var reader = new FileReader()
reader.onload = f => {
  let src = f.target.result
}
reader.readAsDataURL(file)

and here used in the callback after a drop event:

drop(e){
      let files = e.dataTransfer.files

      let file = files[0]

      let reader = new FileReader()
      reader.onload = f => {
        // f.target.result contains the base64 encoding of the image
        let src = f.target.result
      }
      reader.readAsDataURL(file)
}

The above snippet is simplified on purpose to show the relevant part. The fully implemented

Conclusion #

You can check the repository if you want to start from the source. The components are not meant to be a drop-in component but rather a starting point to extend them to something more meaningful in your app. There are two flavuors of the same implementation:

  • DropAnImage to allow uploading only one image
  • DropImages allows many images to be dropped