banky
banky

Reputation: 848

how to preview multiple files before uploading in vue.js

I'm trying to preview multiple images been selected before uploading in vue.js. looks like i'm doing something wrong but can't figure out what. I will appreciate some guidance please. Find below my component:

<template>
  <div class="form-group">
    <textarea name="body" class="form-control" v-model="body" rows="4" placeholder="What's on your mind"></textarea>
  </div>
  <div class="form-group">
    <div v-if="attach">
        <img :src="selectedFile" style="width:70px; height:60px" />
        <button type="button" class="btn btn-danger" @click.prevent="cancelImage">Cancel</button>
    </div>
    <div v-else>
        <input type="file" @change="onFileChange" class="btn btn-default" multiple>
    </div>
  </div>
  <div class="form-group">
    <button type="button" class="btn btn-primary" @click.prevent="sendPost">Post</button>
  </div>
</template>

<script>
    export default {
      data(){
        return {
          body: '',
          images: [],
          attach: false,
          selectedFile: ''
        }
      },
      methods: {
        onFileChange(e){
          var files = e.target.files;
          if(files){
            var files_count = files.length;
            for (let i=0; i<files_count; i++){
              var reader = new FileReader();
              reader.onload = function(e){
                this.selectedFile = e.target.result;
              }
              reader.readAsDataURL(files[i]);
            }
          }
        }
      }
    }
</script>

Upvotes: 6

Views: 10409

Answers (3)

Diwas Poudel
Diwas Poudel

Reputation: 847

This works well.

Html Section

<script src="https://unpkg.com/vue"></script>

<div id="app">
   <input
          type="file"
          multiple
          accept="image/jpeg"
          @change="onFileChange"
          />

  <div v-for="(image, key) in images" :key="key">
    <div>
      <img class="preview" :ref="'image'" />
      {{ image.name }}
    </div>
  </div>
</div>

In JS section

 new Vue({
  el: '#app',
  data: {
    images: [],
  },
   methods: {
    onFileChange(e) {
      let vm = this;
      var selectedFiles = e.target.files;
      for (let i = 0; i < selectedFiles.length; i++) {
        console.log(selectedFiles[i]);
        this.images.push(selectedFiles[i]);
      }

      for (let i = 0; i < this.images.length; i++) {
        let reader = new FileReader();
       reader.onload = (e) => {
          this.$refs.image[i].src = reader.result;

          console.log(this.$refs.image[i].src);
        };

        reader.readAsDataURL(this.images[i]);
      }
    }
  }
})

Working Demo here: https://jsfiddle.net/Diwas_Poudel/1rLgzjvk/8/

Source

Upvotes: 8

The answer of @flexi is quite right. Just one more change var to let to not getting any error.

var selectedFiles = e.target.files;
for (let i=0; i < selectedFiles.length; i++){
    this.images.push(selectedFiles[i]);
}

for (let i=0; i<this.images.length; i++){
    let reader = new FileReader(); //instantiate a new file reader
    reader.addEventListener('load', function(){
      this.$refs['image' + parseInt( i )][0].src = reader.result;
    }.bind(this), false);  //add event listener

    reader.readAsDataURL(this.images[i]);
}

Upvotes: 2

Flexi
Flexi

Reputation: 195

I will introduce a div into the template to hold the files you want to preview:

<div v-for="(image, key) in images">
    <div>
        <img class="preview" v-bind:ref="'image' +parseInt( key )" /> 
        {{ image.name }}
    </div>
</div>

Then to handle the image preview in your onFileChange method;

var selectedFiles = e.target.files;
for (var i=0; i < selectedFiles.length; i++){
    this.images.push(selectedFiles[i]);
}

for (var i=0; i<this.images.length; i++){
    let reader = new FileReader(); //instantiate a new file reader
    reader.addEventListener('load', function(){
      this.$refs['image' + parseInt( i )][0].src = reader.result;
    }.bind(this), false);  //add event listener

    reader.readAsDataURL(this.images[i]);
}

Upvotes: 7

Related Questions