File Upload in Vue.js Using vue-dropzone

Alex Jover Morales

vue-dropzone is a vue component implemented on top of Dropzone.js that provides drag’n’drop functionality for file uploads with image previews.

It’s quite powerful and has many options, although it gives you a great deal of functionality out-of-the-box with almost no configuration. You can do multiple file uploads, cancel them, validate file size and format, show a progress bar, and much more!

Getting Started

Let’s start by installing vue-dropzone:

$ npm install vue2-dropzone

Then, in our main.js entry point file we need to import the CSS file:

import 'vue2-dropzone/dist/vue2Dropzone.css'

Basic Image Upload

In order to create a simple image upload, all you need is to import the component, and use it providing an id an options properties:

<template>
  <div id="app">
    <vue-dropzone id="drop1" :options="dropOptions"></vue-dropzone>
  </div>
</template>

<script>
import vueDropzone from "vue2-dropzone";

export default {
  data: () => ({
    dropOptions: {
      url: "https://httpbin.org/post"
    }
  }),
  components: {
    vueDropzone
  }
};
</script>

The url `https://httpbin.org/post` is an endpoint from an http service that returns a valid response for any HTTP POST call.

More Options

The only required options is url, but there are many more you can use.

For example, let’s say you want:

  • A maximum of 4 files
  • 2 MB max file size
  • Sent in chunks of 500 bytes
  • Set a custom thumbnail size of 150px
  • Make the uploaded items cancelable and removable (by default they’re not)

You could apply all those business rules to the component as follows:

export default {
  data: () => ({
    dropOptions: {
      url: "https://httpbin.org/post",
      maxFilesize: 2, // MB
      maxFiles: 4,
      chunking: true,
      chunkSize: 500, // Bytes
      thumbnailWidth: 150, // px
      thumbnailHeight: 150,
      addRemoveLinks: true
    }
  })
  // ...
}

I think most of this options are quite self explanatory. Just in case, the addRemoveLinks adds a cancel and remove links to each preview of the dropzone.

You can check the full options in the dropzone docs.

Controlling the Dropzone

If we want to implement custom functionality, vue-dropzone exposes several methods that we can access by using a ref on the vue-dropzone tag.

For example, we can implement a button that removes all the uploaded files:

<template>
  <div id="app">
    <vue-dropzone ref="dropzone" id="drop1" :options="dropOptions"></vue-dropzone>
    <button @click="removeAllFiles">Remove All Files</button>
  </div>
</template>

<script>
import vueDropzone from "vue2-dropzone";

export default {
  // ...
  methods: {
    removeAllFiles() {
      this.$refs.dropzone.removeAllFiles();
    }
  }
};
</script>

React to Changes Using Events

There are a bunch of events you can use to perform any kind of action when something happens.

For example, to check when a file has been uploaded we can use the vdropzone-complete event:

<template>
  <div id="app">
    <vue-dropzone
      ref="dropzone"
      id="drop1"
      :options="dropOptions"
      @vdropzone-complete="afterComplete"
    ></vue-dropzone>
    <button @click="removeAllFiles">Remove All Files</button>
  </div>
</template>

<script>
import vueDropzone from "vue2-dropzone";

export default {
  // ...
  methods: {
    afterComplete(file) {
      console.log(file);
    }
  }
};
</script>

You won’t need to use events for many of the common operations, not even for showing a message when an upload fails, or when an upload is cancelled. vue-dropzone gives you all that by default in a customizable form, so before using an event check if that functionality you want is already there.

Styling

In order to customize the style of the dropzone, first you must set the include-styling property to false to turn off the default styling:

<vue-dropzone
  id="drop1"
  :include-styling="false"
></vue-dropzone>

Then provide a previewTemplate options, passing a string with the template and the right structure which is defined by its classes. As a starting point, we can take the template example from the official example:

<vue-dropzone
  id="drop1"
  :options="dropOptions"
  :include-styling="false"
></vue-dropzone>

<script>
const getTemplate = () => `
<div class="dz-preview dz-file-preview">
  <div class="dz-image">
    <div data-dz-thumbnail-bg></div>
  </div>
  <div class="dz-details">
    <div class="dz-size"><span data-dz-size></span></div>
    <div class="dz-filename"><span data-dz-name></span></div>
  </div>
  <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div>
  <div class="dz-error-message"><span data-dz-errormessage></span></div>
  <div class="dz-success-mark"><i class="fa fa-check"></i></div>
  <div class="dz-error-mark"><i class="fa fa-close"></i></div>
</div>
`;

export default {
  data: () => ({
    dropOptions: {
      previewTemplate: getTemplate()
    }
  })
}
</script>

Then it’ll be possible to style it using CSS by targeting the different class names:

<style>
  #drop1 {
    height: 200px;
    padding: 40px;
    color: white;
    background: black;
  }

  #drop1 .dz-preview {
    width: 160px;
  }
  /* ... */
</style>

Wrapping Up

I hope this introduction has given you a starting point to go and play with vue-dropzone yourself.

You can find a working demo and the code from this article in this Codesandbox.


You can also check out these related posts of ours to explore the topic more in-depth:

Stay cool 🦄

  Tweet It

🕵 Search Results

🔎 Searching...

Sponsored by #native_company# — Learn More
#native_title# #native_desc#
#native_cta#