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: / (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);
}
}
})
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);
}
}
})
Share
Improve this question
asked Dec 28, 2015 at 18:15
ChrisSChrisS
7442 gold badges8 silver badges21 bronze badges
4 Answers
Reset to default 4The reason why the console.log
is not displaying anything is because FileReader.readAsText()
is asynchronous. It pletes 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.
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);
}
);
}
}
});
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
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('plete');
};
} 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
}
}
});