Within my application, there is a form located in the ManageCards
component. This form includes a child component called ImageUpload
, which emits an image file and its local URL to the parent component:
<form class="mb-3">
<div class="form-group">
<h4>{{card.description}}</h4>
<textarea class="form-control" :placeholder="card.description" v-model="card.description"></textarea>
</div>
<div>
<img v-if="card.picture" class="img-circle" style="width:150px" v-bind:src="card.picture"></img>
</div>
<div id="preview"”>
<h4>Preview</h4>
<ImageUpload :imgUrl="url" @newPicture="updatePicture"></ImageUpload>
<button @click="addCard" type="button" class="btn btn-primary btn-block" style="color:white">Save</button>
</div>
</form>
The method addCard
initiates a POST request to send data to the API:
addCard() {
const formData = new FormData();
formData.append('title', this.card.title);
formData.append('description', this.card.description);
formData.append('imagefile', this.selectedFile);
formData.append('game_id', this.currentGame.id);
// ...
}
The values of SelectedFile and card.picture should be updated by the emitted method updatePicture
:
updatePicture(imageData) {
console.log("Received emit");
this.selectedFile = imageData.file;
this.card.picture = imageData.picture;
// ...
}
The structure of the ImageUpload
Component is as follows:
<template>
<div class="Image-Upload-wrapper Image-upload">
<div>
<input type="file" v-on:change="onFileChange" ref="fileUpload" id="file_picture_input"></input>
<label for="file_picture_input" class="upload_picture_button">Choose Image</label>
</div>
<div id="croppie"></div>
<div class="upload-wrapper">
<button type="button" class="btn btn-primary btn-sm" v-on:click="setImage"&rt;
Set image
</button>
</div>
</div>
</template>
<script>
// Croppie explanation::https://www.youtube.com/watch?v=kvNozA8M1HM
import Croppie from 'croppie';
export default {
props: [
'imgUrl'
],
mounted() {
this.setUpCroppie()
},
data() {
return {
croppie: null,
croppieImage: '',
selectedFile: '',
picture: '',
url: '',
}
},
methods: {
setUpCroppie() {
let el = document.getElementById('croppie');
this.croppie = new Croppie(el, {
viewport: { width: 200, height:200, type:'circle' },
boundary: { width: 220, height:220 },
showZoomer: true,
enableOrientation: true
});
this.croppie.bind({
url: this.url
});
},
setImage() {
this.croppie.result({
type: 'canvas',
size: 'viewport'
})
.then(blob =>fetch(blob))
.then(res => res.arrayBuffer)
.then(buf => new File([buf], this.croppieImage.name, { type:'image/png' }))
.then(file => {
this.croppieImage = file;
this.picture = URL.createObjectURL(this.croppieImage);
const imageData = {
picture: this.picture,
file: this.croppieImage
};
console.log("Ready to emit...?");
this.$emit('newPicture', imageData);
this.url = '';
})
},
onFileChange(e) {
if (e.target.files && e.target.files.length > 0) {
this.selectedFile = e.target.files[0];
console.log("chosen file is: " + this.selectedFile.name);
this.url = URL.createObjectURL(this.selectedFile);
this.croppie.bind({
url: this.url
});
} else {
// No image selected, set it to a default value (e.g. an empty string)
this.selectedFile = null;
this.url = '';
}
}
},
}
</script>
I am able to see the message Ready to emit...?
in the console output from the setImage
method in the child component. However, I do not see the message Received emit
from the emit method in the parent component. As a result, the necessary fields for the POST command remain unpopulated.
If anyone can identify the mistake I might be making (probably something trivial), please do let me know!