javascriptajaxlaraveldropzone.js

Dropzone remove on click fires the xhr request multiple times


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>&nbsp;
            </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.

Four Images no network calls Removed one and four xhr calls

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.


Solution

  • 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);
                    });
           });