0

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>
1

2 Answers 2

2

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

Sign up to request clarification or add additional context in comments.

1 Comment

I had already tried your first approach without success since the image is empty at the time upload() is called (which is why image is logged). Tried the second one, turns out the same.
0

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
    }
  }
  // ...
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.