I've got a Vue app with an upload component which gets an image (dropzone), pass it to cropper (cropperjs) and returns it to dropzone once cropped.
I want to compress image just before the upload, so i'm gonna get the image from the dropzone object and pass it to the compressor (compressorjs). I'm struggling with an error and can't go further.. that's the situation:
Cropping method:
cropImage() {
// get image data for post processing, e.g. upload or setting image src
this.$refs.cropper.getCroppedCanvas().toBlob((blob)=> {
var croppedFile = this.blobToFile(blob, this.fileName)
croppedFile.accepted = true
this.$refs.myVueDropzone.dropzone.addFile(croppedFile)
this.cropperReset()
});
},
At this point my dropzone gets the cropped images and produces correctly the cropper thumbnail.
Now i'm gonna to launch the upload method, but compressing the image just before processing the queue.
launchUpload() {
new Compressor(this.$refs.myVueDropzone.dropzone.files[0], {
quality: 0.6,
maxWidth: 250,
minWidth: 250,
success(compressedResult){
this.testFunction(compressedResult)
},
error(err) {
console.log(err.message);
},
})
/*await this.$refs.myVueDropzone.processQueue()
this.$refs.myVueDropzone.removeAllFiles()*/
}
I'm gonna pass the file to the Compressor, pass some settings and getting the "compressedResult" blob which is the compressed version of the image. My problem is that using testFunction into it results in:
"Uncaught TypeError: this.testFunction is not a function"
testFunction is just a dummy function that i made after trying everything else..
testFunction(compressed){
this.$refs.myVueDropzone.removeAllFiles()
this.$refs.myVueDropzone.addFile(compressed)
},
console.log into testFunction results "undefined" and nothing seems to work..
Every method i posted here is part of "methods" objects of the Vue component.
Vue part where the components interact:
<v-dialog
v-model="is_show"
persistent
max-width="800px"
>
<v-card>
<v-card-title>
<span class="text-h5">Upload File</span>
</v-card-title>
<v-card-text>
<vue-dropzone
ref="myVueDropzone"
id="dropzone"
:options="dropzoneOptions"
@vdropzone-file-added="(file) => passToCropper(file)"
@vdropzone-complete="reloadAndClose"
></vue-dropzone>
<v-col cols="12" class="text-right">
<v-btn
@click="closeModal"
class="ma-2"
:disabled="loading"
>
Close
</v-btn>
<v-btn
@click="launchUpload"
class="ma-2"
color="primary"
:loading="loading"
>
Submit
</v-btn>
</v-col>
</v-card-text>
</v-card>
</v-dialog>
Everything works perfectly if i don't compress the image and process my dropzone queue just after the "addFile" part into cropImage method.
Many thanks!!
You should use an arrow function expression instead of a function expression because using a function expression it creates its own this
binding.
So in your case testFunction
doesn't exist in the new context (the new this
).
success(compressedResult){
this.testFunction(compressedResult)
},
See how this
refers to the global object in case of an arrow function expression and how this
refers to the object the method is called on in case of a function expression :
const obj = {
someProperty: 'someProperty',
a: () => {
console.log(this === window, this === obj)
},
b() {
console.log(this === window, this === obj)
}
}
obj.a()
obj.b()
You can also keep your function expression and use a stored reference of this
like :
launchUpload() {
const that = this;
new Compressor(this.$refs.myVueDropzone.dropzone.files[0], {
quality: 0.6,
maxWidth: 250,
minWidth: 250,
success(compressedResult){
that.testFunction(compressedResult)
},
error(err) {
console.log(err.message);
},
})
/*await this.$refs.myVueDropzone.processQueue()
this.$refs.myVueDropzone.removeAllFiles()*/
}