1

My component vue is like this :

<template>
    <div class="modal" tabindex="-1" role="dialog">
        <div class="modal-dialog" role="document">
            <div class="modal-content">
                <form method="post" :action="baseUrl+'/product/editImage'" enctype="multipart/form-data">
                    ...
                    <input type="file" v-on:change="changeImage" name="image" id="image" required>
                    ...
                </form>
            </div>
        </div>
    </div>
</template>
<script>
    export default{
        ...
        methods: {
            changeImage(e) {
                data = new FormData();
                data.append('file', $('#image')[0].files[0]);
                var imgname  =  $('#image').val();
                var size  =  $('#image')[0].files[0].size;
                var ext =  imgname.substr( (imgname.lastIndexOf('.') +1) );
                if(ext=='jpg' || ext=='jpeg' || ext=='png' || ext=='gif' || ext=='PNG' || ext=='JPG' || ext=='JPEG') {
                    if(size<=5000000) {
                        $.ajax({
                            url: window.Laravel.baseUrl+'/product/addImage',
                            type: "POST",
                            data: data,
                            enctype: 'multipart/form-data',
                            processData: false,  // tell jQuery not to process the data
                            contentType: false   // tell jQuery not to set contentType
                        }).done(function(data) {
                            if (!$.trim(data)) {   
                                alert('No response');
                            }
                            else {   
                                var files = e.target.files || e.dataTransfer.files
                                if (!files.length)
                                    return;
                                this.createImage(files[0])
                                this.imageChanged = files[0]
                                $('#image').val(data);
                            }
                        });
                        return false;
                    }
                    else {
                        alert('Sorry File size exceeding from 5 Mb');
                        $('#image').val('');
                    }
                }
                else {
                    alert('Sorry Only you can uplaod JPEG|JPG|PNG|GIF file type ');
                }
            },
            createImage(file) {
                var image = new Image()
                var reader = new FileReader()
                var vm = this

                reader.onload = (e) => {
                    vm.image = e.target.result
                };
                reader.readAsDataURL(file)
            },
        } 
    }
</script>

I still use javascript in vue.js 2. because i am still confused when using vue.js as a whole

When I upload image, there exist error like this :

Uncaught ReferenceError: data is not defined

Seems data = new FormData(); not working on the vue.js

I had try it use javascript and it works

But when I implement it to vue.js, it does not work

How can I solve the problem?

moses toh
  • 12,344
  • 71
  • 243
  • 443
  • 1. 'Seems data = new FormData(); not working on the vue.js' should not be the cause. – Jin Jun 02 '17 at 02:58
  • @J Jin, So what is the solution? – moses toh Jun 02 '17 at 03:01
  • In 'data = new FormData()' , where do you define 'data' or can you use 'var data = new FormData()'. And in '.done(function(data)', can you use other name except 'data' – Jin Jun 02 '17 at 03:05
  • @J Jin, Now it works. I use like this : `let myForm = document.getElementById('myForm'); let data = new FormData(myForm);` – moses toh Jun 02 '17 at 03:13

2 Answers2

3

I've re-worked your code a bit to make better use of Vue. jQuery is no longer used aside from the ajax submission.

new Vue({
  el:"#app",
  data:{
    allowableTypes: ['jpg', 'jpeg', 'png', 'gif'],
    maximumSize: 5000000,
    selectedImage: null,
    image: null,
    options:{
      url: 'https://httpbin.org/post',
      type: "POST",
      processData: false, 
      contentType: false 
    }
  },
  methods: {
    validate(image) {
      if (!this.allowableTypes.includes(image.name.split(".").pop().toLowerCase())) {
        alert(`Sorry you can only upload ${this.allowableTypes.join("|").toUpperCase()} files.`)
        return false
      }

      if (image.size > this.maximumSize){
        alert("Sorry File size exceeding from 5 Mb")
        return false
      }

      return true
    },
    onImageError(err){
      console.log(err, 'do something with error')
    },
    changeImage($event) {
      this.selectedImage = $event.target.files[0]
      //validate the image
      if (!this.validate(this.selectedImage))
        return
      // create a form
      const form = new FormData();
      form.append('file', this.selectedImage);
      // submit the image
      $.ajax(Object.assign({}, this.options, {data: form}))
        .then(this.createImage)
        .catch(this.onImageError);
    },
    createImage() {
      const image = new Image()
      const reader = new FileReader()
      reader.onload = (e) => {
        this.image = e.target.result
      };
      reader.readAsDataURL(this.selectedImage)
    },
  } 
})

Template

<div id="app">
  <input type="file" v-on:change="changeImage" name="image">
  <input v-if="selectedImage" v-model="selectedImage.name" type="hidden" name="photo" />
  {{image}}
</div>

Example.

Bert
  • 80,741
  • 17
  • 199
  • 164
  • Can you update the const onDone? I update it like this : `const onDone = (data) => {if (!$.trim(data)) { alert('No response'); } else { var files = $event.target.files || $event.dataTransfer.files if (!files.length) return; this.createImage(files[0]) this.imageChanged = files[0] $('#image_changed').val(data); } }` – moses toh Jun 02 '17 at 03:39
  • I used to display image. I try like that, But there exist error : `Uncaught DOMException: Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string.` – moses toh Jun 02 '17 at 03:40
  • @TrendingNews is `#image_changed` an `img` element? – Bert Jun 02 '17 at 03:42
  • sorry I mean `$('#image').val(data);` – moses toh Jun 02 '17 at 03:44
  • @TrendingNews It's not allowed to set the value for a file input element. https://stackoverflow.com/q/1696877/38065 – Bert Jun 02 '17 at 03:45
  • Sorry again. Should it like this : `$('#photo').val(data);`. So I have input hidden like this : `` – moses toh Jun 02 '17 at 03:51
  • @TrendingNews And what do you want to be the value? The data url? – Bert Jun 02 '17 at 03:53
  • The value is filename – moses toh Jun 02 '17 at 03:55
  • @TrendingNews Updated. – Bert Jun 02 '17 at 04:09
  • I had solve it. Before there is a little mistake. I want to ask last. Like this : `const payload = {id_product: this.idProduct, } this.$store.dispatch('editImage', payload)`. It is ajax vue.js. If you can use that. You can update your answer. So there are 2 options, namely it using ajax javascript and it also using ajax vue.js – moses toh Jun 02 '17 at 04:11
  • @TrendingNews I'm not sure I understand your question. – Bert Jun 02 '17 at 04:13
  • Have you ever used dispatch to call vuex store? – moses toh Jun 02 '17 at 04:14
  • @TrendingNews Vuex is not really my area of expertise. – Bert Jun 02 '17 at 04:15
  • I think you master vue.js – moses toh Jun 02 '17 at 04:16
  • Okay. Thanks a lot for your help – moses toh Jun 02 '17 at 04:17
  • @TrendingNews I've never needed Vuex on a project. It's not a bad tool, I just feel that it is overkill in many cases :) – Bert Jun 02 '17 at 04:17
  • Okay. Thanks again for your help :) – moses toh Jun 02 '17 at 04:21
0

This plugin may work for you: Vue.ajax
Its file upload feature is available:

HTML

<input type="file" name="my-input" id="my-input">

VueJS

Vue.ajax.post('http://example.com', [data], {
  fileInputs: [
    document.getElementById('my-input')
  ]
});

I actually created this for myself, but then I decided to publish it in Github. I hope you will take your interest.

Fatih Koca
  • 147
  • 1
  • 5