I'm working with laravel and added in an image uploader using Dropzonejs 5x and ran into a really odd issue where when there are more than one image uploaded, if I click remove on one, it fires off the xhr request for the image I click removed on, but it fires the request a number of times equal to how many images I have total.
I'm pulling in dropzone via cdn and am using dropzone declaratively according to the docos.
Here is the blade file
<div class="panel panel-default" id="dashboard-recent">
<div class="panel-heading" >
<span class="panel-title">
<i class="panel-title-icon fa fa-picture-o hidden-xs"></i>
</span>
<form action="/requests/{{$request->id}}/photo-upload" class="dropzone" id="request-photo-upload">
@csrf
@method('POST')
</form>
</div>
</div>
@section('head-styles')
<link rel="stylesheet" href="https://unpkg.com/dropzone@5/dist/min/dropzone.min.css" type="text/css" />
<style>
.dropzone{
.dz-preview{
.dz-image{
img{
height: 100%;
width:100%;
object-fit: cover;
}
}
}
}
</style>
@stop
@section('head-scripts')
<script src="https://unpkg.com/dropzone@5/dist/min/dropzone.min.js"></script>
<script src="/js/requests-dropzone.js" id="requests-dropzone" request="{{$request->id}}"></script>
@stop
Here is the javascript to handle Dropzone
@section('javascripts')
<script>
let endpoint = "/requests/{{$request->id}}/photo-upload";
Dropzone.options.requestPhotoUpload = {
paramName: "file",
maxFiles: 5,
maxFilesize: 4, // MB
uploadMultiple: true,
parallelUploads: 1,
addRemoveLinks: true,
dictRemoveFile: "Delete",
init: function() {
this.on("success", function(file, serverResponse) {
var fileuploded = file.previewElement.querySelector("[data-dz-name]");
fileuploded.innerHTML = serverResponse.newfilename;
});
this.on("addedfile", function(file) {
file.previewElement.querySelector('[data-dz-name]').textContent = file.upload.filename;
});
this.on("complete", function(file) {
$(".dz-remove").html("<div><span class='fa fa-trash text-danger' style='font-size: 1.5em'></span></div>").on('click', function(e) {
e.preventDefault();
e.stopPropagation();
let imageId = $(this).parent().find(".dz-filename > span").text();
let uri = endpoint + `/${imageId}`;
axios.delete(uri)
.then(response => {
console.log(`Deleted photo with ID ${imageId}`);
})
.catch(error => {
console.error(error);
});
});
});
let thisDropzone = this;
axios.get(endpoint)
.then(response => {
this.data = response.data;
this.data.forEach(function(item) {
let mockFile = {"name": item.name, "request": item.request, "size": item.size, "path": item.path};
thisDropzone.options.addedfile.call(thisDropzone, mockFile);
thisDropzone.options.thumbnail.call(thisDropzone, mockFile, mockFile.path);
thisDropzone.emit("complete", mockFile);
});
})
.catch(error => {
console.error(`Error fetching request ${this.request.id}`, error)
})
}
};
</script>
@stop
I can see in the network tab when I click the trash can on a single image that it calls the correct endpoint with the correct method (delete) but it does it four times (because I have four images total). I'm attaching two screenshots showing first four images, then only three and the four total xhr calls, additionally I do see three console logs of image deletion so the click event seems to be firing multiple times off a single click.
I'm sure it's something I'm not doing correctly in the dz-remove onclick but I cannot for the life of me figure out what it is.
In case anyone else runs into something similar I solved this by moving the ajax call into it's own event handle, which I able to find looking at the actual source code in options.js
this.on("removedfile", function(file){
filename = file.name.split('.')
let uri = endpoint + `/${filename[0]}`;
console.log(uri);
axios.delete(uri)
.then(response => {
console.log(`Deleted photo with ID ${file.name}`);
})
.catch(error => {
console.error(error);
});
});