7

I'm trying to get the input of a .csv File, after I choose it with my Html 5 input field. Therefor I use a onFileChange method and a FileReader(). Here is an example I used: http://codepen.io/Atinux/pen/qOvawK/ (except that I want to read the text input, and not an image file).

My Problem is, that I get an empty input on the first try, but on the second try it works. Why is that? Any ideas? (I'm a javascript beginner ;) )

html:

<form enctype="multipart/form-data">
    <input type="file" @change="onFileChange">
</form>

js:

new Vue({
    el: '#app',
    data: {
        fileinput: ''
    },
    methods: {
        onFileChange(e) {
            var files = e.target.files || e.dataTransfer.files;
            if (!files.length)
                return;
            this.createInput(files[0]);
        },
        createInput(file) {
            var reader = new FileReader();
            var vm = this;
            reader.onload = (e) => {

            vm.fileinput = reader.result;
            }
            reader.readAsText(file);

            console.log(this.fileinput);
        }

    }
})

4 Answers 4

4

The reason why the console.log is not displaying anything is because FileReader.readAsText() is asynchronous. It completes after the console.log has executed.

You can typically deal with this by putting a watch on fileInput or throwing a local event using vm.$emit from the onload handler.

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

Comments

2

Here you can handle async code using Promise function

new Vue({
  el: "#app",
  data: {
    fileinput: ""
  },
  methods: {
    onFileChange(e) {
      var files = e.target.files || e.dataTransfer.files;
      if (!files.length) return;
      this.createInput(files[0]);
    },
    createInput(file) {
      let promise = new Promise((resolve, reject) => {
        var reader = new FileReader();
        var vm = this;
        reader.onload = e => {
          resolve((vm.fileinput = reader.result));
        };
        reader.readAsText(file);
      });

      promise.then(
        result => {
          /* handle a successful result */
          console.log(this.fileinput);
        },
        error => {
          /* handle an error */ 
          console.log(error);
        }
      );
    }
  }
});

Comments

2

Here's another way

        onFileChange: function(e) {
            const file = e.target.files[0];
            const reader = new FileReader();
            reader.onload = e => console.log(e.target.result);
            reader.readAsText(file);
        },

Reference Creating a Vue.js File Reader Component Using the FileReader API

Comments

0

Here you can also try as below if you want separate function after promise and define in data.

    new Vue({
    el: "#app",
    data: {
        fileinput: ""
    },
    methods: {
        readFile: function(evt) {
            const scope = this
            var promiseVar = new Promise(async (resolve, reject) => {
                try {
                    var reader = new FileReader();
                    var file = evt.target.files[0];
                    reader.readAsText(file);
                    reader.onload = function(e) {
                        scope.fileinput = e.target.result
                        resolve('complete');
                    };
                } catch (error) {
                    console.error(error);
                    reject("There must be an error");
                }
            });
            // let updateds = await Promise.all(promiseVar);
            promiseVar.then(data=>{
                scope.afterRead();
            })
        },
        afterRead:function(){
            console.log(this.fileinput)
            // write your logic for import 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.