How do I get this example to work with two way binding?
I am creating a file upload component in vue like:
window.Vue.component('base64fileupload', {
template:
'<input type="file" @change="on_file_changed()"/>',
methods:
{
on_file_changed()
{
var self = this;
var reader = new FileReader();
var file = this.$el.files[0];
reader.readAsDataURL(file);
reader.onloadend = function (evt)
{
if (evt.target.readyState == FileReader.DONE)
{
self.$emit('filename', file.name)
self.$emit('filedata', evt.target.result)
}
}
}
}
});
and use the following html:
<base64fileupload @filename="file_edit.filename = $event"
@filedata="file_edit.filedata = $event"></base64fileupload>
However, that is a bit manual, I expect to be able to bind data instead of using event handlrers. However, $emit
is the only thing I have got working, despite a lot of testing and googling.
I have tried data()
and props
and self.$forceUpdate()
in numerous ways.
It is not very easy to well why this is not googlable right away, but what I always find is typescript examples and usage of inside .vue-files, none of which I use.
CodePudding user response:
It seems that you've a reactivity issue, to solve it use the this.$set
method to mutate the inner fields :
<base64fileupload @filename="$set(file_edit,'filename', $event)"
@filedata="$set(file_edit, 'filedata', $event)"></base64fileupload>
If you want two way binding, you've to define prop named value
and emit an event called input
(this valid for vue 2) :
base64fileupload :
window.Vue.component('base64fileupload', {
template:
'<input type="file" :value="value" @change="on_file_changed"/>',
props:['value'],
methods:
{
on_file_changed()
{
var self = this;
var reader = new FileReader();
var file = this.$el.files[0];
reader.readAsDataURL(file);
reader.onloadend = function (evt)
{
if (evt.target.readyState == FileReader.DONE)
{
self.$emit('input', {name:file.name, filedat:evt.target.result})
}
}
}
}
});
Use it like :
<base64fileupload v-model="file_edit"></base64fileupload>
CodePudding user response:
You could create your own custom FileUpload component and then it could be simpler to just v-model it.
FileUpload.vue
<template>
<div>
<input type="file" :value="modelValue" @input="onFileInputChange" />
</div>
</template>
<script>
export default {
name: 'FileUpload',
data() {
return {
modelValue: null,
};
},
methods: {
onFileInputChange(event) {
let reader = new FileReader();
console.log(event.target.files);
let file = event.target.files[0];
reader.readAsDataURL(file);
reader.onloadend = (evt) => {
if (evt.target.readyState == FileReader.DONE) {
this.$emit('update:modelValue', {
name: file.name,
data: evt.target.result,
});
}
};
},
},
};
</script>
Use it like.
<FileUpload v-model="file" />