URL: https://www.progressiverobot.com/vuejs-uploading-vue-picture-input/

File and image uploads are a must-have feature for many non-trivial apps. Lucky for us, it's easy to setup in Vue apps with vue-picture-input.

Check this post of ours if you're looking to create your own custom file selector input.

Installation

image illustration for: Installation

Install vue-picture-input via npm or Yarn:

				
					
$ npm install --save vue-picture-input



# or:

$ yarn add vue-picture-input

				
			

Usage

The vue-picture-input library allows for a variety of usages, and is very simple to use:

				
					
<template>

 <picture-input



 <!--Props go here-->



 ></picture-input>

</template>

				
			

Here are a few props that we're going to make use of:

  • <^>ref<^>: We'll need this to access the base64 image string
  • <^>width<^>, <^>height<^>: Dictate the width and height of the component
  • <^>accept<^>: Used to restrict accepted file types
  • <^>removable<^>: Specifies whether the component can be reset or not

Additionally, the component emits the following events:

  • <^>removed<^>: emitted when picture is detached from component
  • <^>changed<^>: emitted when the selected picture is changed (ie. reselected)

Here's what our code looks like for the file input:

				
					
[label index.vue]

&lt;picture-input

 ref="pictureInput"

 @change="onChanged"

 @remove="onRemoved"

 :width="500"

 :removable="true"

 removeButtonClass="ui red button"

 :height="500"

 accept="image/jpeg, image/png, image/gif"

 buttonClass="ui button primary"

 :customStrings="{

 upload: '&lt;h1&gt;Upload it!&lt;/h1&gt;',

 drag: 'Drag and drop your image here'}"&gt;



&lt;/picture-input&gt;

				
			

Let's add a button that will allow us to upload the selected image to our backend.

It basically calls the <^>attemptUpload<^> method when clicked and has the disabled class binding. It'll only be enabled if there's a selected image:

				
					
&lt;button @click="attemptUpload" v-bind:class="{ disabled: !image }"&gt;

 Upload

&lt;/button&gt;

				
			

Next, we'll use Axios to make network requests. We'll also leverage the Formdata API to create a sweet composition for posting image data:

				
					
[label upload.js]

import axios from 'axios';



export default function (url, file, name = 'avatar') {

 if (typeof url !== 'string') {

 throw new TypeError(`Expected a string, got ${typeof url}`);

 }



 // You can add checks to ensure the url is valid, if you wish



 const formData = new FormData();

 formData.append(name, file);

 const config = {

 headers: {

 'content-type': 'multipart/form-data'

 }

 };

 return axios.post(url, formData, config);

};



				
			

The above code accepts a url as the first parameter and a file object as the second parameter then returns a promise. It also sets the header's <^>content-type<^> to multipart/formdata so our backend API can tell what's in the pipes.

We can therefore use the above code as so:

				
					
import FormDataPost from '/upload';



//...



FormDataPost('http://localhost:8001/user/picture', image)

 .then(response=&gt;{

 console.log("Uploaded picture successfully");

 })

 .catch(err=&gt;{

 console.error(err);

 });



 //...

				
			

Here's what our <^>onChanged<^>, <^>onRemoved<^> and <^>attemptUpload<^> methods look like:

				
					
//...



methods: {

 onChanged() {

 console.log("New picture loaded");

 if (this.$refs.pictureInput.file) {

 this.image = this.$refs.pictureInput.file;

 } else {

 console.log("Old browser. No support for Filereader API");

 }

 },

 onRemoved() {

 this.image = '';

 },

 attemptUpload() {

 if (this.image){

 FormDataPost('http://localhost:8001/user/picture', this.image)

 .then(response=&gt;{

 if (response.data.success){

 this.image = '';

 console.log("Image uploaded successfully ✨");

 }

 })

 .catch(err=&gt;{

 console.error(err);

 });

 }

 }

}



//...

				
			

💪 Done! Our image upload is working on the frontend. Read-on for how to set this up on a Node.js backend using Express.