Home » vue » Vue Js – Sending axios request after file input changes

Vue Js – Sending axios request after file input changes

Posted by: admin November 26, 2021 Leave a comment

Questions:

EDIT

This answer does solve a problem on running two different functions back to back. Nevertheless, my question deals specifically with the behavior of a file handling input and the moment in which to chain a second event (solved by the second example in @Igor ‘s answer).

QUESTION

I have a file upload Vue component which works perfectly fine. The improvement I would like to make is for it to work on “one click”, meaning the upload() method should be triggered in response to the createImage() finishing. How would I do that?

<template>
<div>
    <div>
        <label>Image:</label>
        <img :src="(image) ? image : tempImage" class="img-fluid">
        <div class="custom-file">
            <input type="file" v-on:change="onFileChange" class="custom-file-input"
            :class="{ 'border-0':image }">
            <label class="custom-file-label" for="customFile">
                {{ filename ? filename : 'Choose pic' }}
            </label>
        </div>
    </div>
    <div>
        <button class="btn btn-success btn-block" 
        :disabled="!image"
        @click.prevent="upload">
            Upload
        </button>
    </div>
</div>
</template>
<script>
    export default{
        props: ['tempImage'],
        data(){
            return {
                image: '',
                filename: ''
            }
        },
        methods: {
            onFileChange(e) {
                let files = e.target.files || e.dataTransfer.files;
                this.$parent.uploading = true;
                if (!files.length)
                    return;
                this.createImage(files[0]);
            },
            createImage(file) {
                let reader = new FileReader();
                let vm = this;
                reader.onload = (e) => {
                    vm.image = e.target.result;
                };
                reader.readAsDataURL(file);
                vm.filename = file.name;
            },
            upload(){
                console.log(this.image);
                axios.post('/api/upload',{image: this.image}).then(res => {
                    if( !res.data.errors ){
                       this.$parent.tempData.image = res.data.src;
                       this.$parent.uploading = false;
                    } else {
                        console.log(res.data.errors);
                    }
                });
            }
        }
    }
</script>
Answers:

What about calling upload() from createImage()?

createImage(file) {
  let reader = new FileReader();
  let vm = this;
  reader.onload = (e) => {
    vm.image = e.target.result;
    vm.filename = file.name;
    this.upload();
  };
  reader.readAsDataURL(file);
}

Or passing upload() as a callback:

onFileChange(e) {
  let files = e.target.files || e.dataTransfer.files;
  this.$parent.uploading = true;
  if (!files.length)
    return;
  this.createImage(files[0], this.upload);
},
createImage(file, callback) {
  let reader = new FileReader();
  let vm = this;
  reader.onload = (e) => {
    vm.image = e.target.result;
    vm.filename = file.name;
    if (callback) callback();
  };
  reader.readAsDataURL(file);
}

Fiddle

###

You start off by creating a variable isUploading with an initial value of false. Then in your method upload you first check if the isUploading variable is false, if it is false, start upload, otherwise, either do nothing or inform the user that the page is still uploading image.

The code could look like this:

var isUploading = false;
export default {
  // ...
  upload() {
    // If not uploading anything start the upload
    if (!isUploading) {
      isUploading = true;
      console.log(this.image);
      axios.post('/api/upload', {
        image: this.image
      }).then(res => {
        if (!res.data.errors) {
          this.$parent.tempData.image = res.data.src;
          this.$parent.uploading = false;
        } else {
          console.log(res.data.errors);
        }
      });
    } else {
      // Do other stuff here
    }
  }
  // ...
}