How to Build Image Preview Vue 2 Component

Last Updated on by in Vue JS
In this tutorial, we will learn how to create a custom image preview feature in a vue application. However, there are plenty of plugins available that can allow you to handle image preview in vue within minutes.If you want to show image preview before it gets uploaded to the server in Vue.js than you are at the right place.

Image Preview in Vue.js Example

If you are a beginner in Vue application development, then you must check out our previously written tutorials on image uploading.

Upload Single & Multiple Images in Vue with Node & Express.

Image preview is a way to show which image is being uploaded to the user. It is considered a good practice to show image preview in Vue before the image uploaded.

Initializing Vue Project

Let’s set up the environment by setting up a basic vue project. We need to install the vue project using vue CLI, run the following command.

vue create vue-image-preview

Get inside the project:

cd vue-image-preview

Node.js Gatsby error – “digital envelope routines::unsupported …”

Error: digital envelope routines::unsupported

opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ],
library: 'digital envelope routines',
reason: 'unsupported',
code: 'ERR_OSSL_EVP_UNSUPPORTED'

To remove above error for invoking the app, make sure to update the "scripts": [] array in package.json file.

"scripts": {
    "serve": "export NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve",
    "build": "export NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service build",
    "lint": "export NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service lint"
},

Now, we have to add the given dependencies in the vue project.

npm install sass-loader node-sass

Create Image Preview Component

Now, we have to create components/FilePreview.vue file. In this component, we will be writing code that will show us the instant image preview in vue.

Open the FilePreview.vue file and add the vue template in it.

In the vue template, we defined the HTML tags: The imagePreviewWrapper div will receive the image link, and image will be added as a background image via the previewImage data variable. The selectImage property corresponds to the click event.

A user will communicate with <input type="file">. This will work as a file picker, and we will choose a file and process the image using the FileReader API.

<template>
  <div>
    <div
      class="imagePreviewWrapper"
      :style="{ 'background-image': `url(${previewImage})` }"
      @click="selectImage">
    </div>

    <input
      ref="fileInput"
      type="file"
      @input="pickFile">
  </div>
</template>

Next, add the following code in the FilePreview.vue component.

<script>
export default {
  data() {
      return {
        previewImage: null
      };
    },
  methods: {
      selectImage () {
          this.$refs.fileInput.click()
      },
      pickFile () {
        let input = this.$refs.fileInput
        let file = input.files
        if (file && file[0]) {
          let reader = new FileReader
          reader.onload = e => {
            this.previewImage = e.target.result
          }
          reader.readAsDataURL(file[0])
          this.$emit('input', file[0])
        }
      }
  }
}
</script>

The previewImage holds the image data or preview url.

The pickFile method triggers when the user selects the image using file input.

Inside the pickFile() function, we are taking the help of FileReader web API, and This API will help us choosing the file and convert it to DataURL using the readAsDataURL method.

The readAsDataURL method is used to read the contents of the specified Blob or File. When the read operation is finished, the readyState becomes DONE, and the loadend is triggered. At that time, the result attribute contains the data as a data: URL representing the file’s data as a base64 encoded string.
MDN Docs

We will add the base64 data as a background image url to show the image preview. However, we are not going to store the base64 URL on the server.

Finally, we need to add the little bit of style for the image preview block at the bottom of the vue component:

<style scoped lang="scss">
.imagePreviewWrapper {
    width: 250px;
    height: 250px;
    display: block;
    cursor: pointer;
    margin: 0 auto 30px;
    background-size: cover;
    background-position: center center;
}
</style>

Here is the final code that directly goes to FilePreview.vue component.

<template>
  <div>
    <div
      class="imagePreviewWrapper"
      :style="{ 'background-image': `url(${previewImage})` }"
      @click="selectImage">
    </div>

    <input
      ref="fileInput"
      type="file"
      @input="pickFile">
  </div>
</template>

<script>
export default {
  data() {
      return {
        previewImage: null
      };
    },
  methods: {
      selectImage () {
          this.$refs.fileInput.click()
      },
      pickFile () {
        let input = this.$refs.fileInput
        let file = input.files
        if (file && file[0]) {
          let reader = new FileReader
          reader.onload = e => {
            this.previewImage = e.target.result
          }
          reader.readAsDataURL(file[0])
          this.$emit('input', file[0])
        }
      }
  }
}
</script>

<style scoped lang="scss">
.imagePreviewWrapper {
    width: 250px;
    height: 250px;
    display: block;
    cursor: pointer;
    margin: 0 auto 30px;
    background-size: cover;
    background-position: center center;
}
</style>

Next, move on to App.vue file and insert the following code into the file.

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

<script>
import FilePreview from "./components/FilePreview";
export default {
  name: "App",
  components: {
    FilePreview,
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

Now, you can start the vue project:

npm run serve

Digamber - Author positronX.io

Hi, I'm Digamber Singh, a New Delhi-based full-stack developer, tech author, and open-source contributor with 10+ years' experience in HTML, CSS, JavaScript, PHP, and WordPress.