Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Reached's avatar

Multiple dropzone.js on one page - access "this"

Hi everyone,

Here is (probably) a nub javascript question:

I want to have multiple dropzones on the same page, so that the user can upload images in different locations on the page. Whenever the upload to the server is successful, the server sends back the new path of the uploaded image, which is then inserted into the closest div as a background image, or in the closest image instead of the src attribute.

It actually works alright, but the two dropzones are "linked together", so when I upload an image in one of them, it is also shown in the other location. How do I make sure that the image is only uploaded to the field where the dropzone was initialized from?

My JS:

var dropzone = $(".image-upload").dropzone({
        url: "/upload-image",
            maxFiles: 1,
            paramName: 'photo',
            addRemoveLinks: true,
            sending: function(file, xhr, formData) {
                formData.append('_token', $('meta[name="_token"]').attr('content'));
                formData.append('name', 'header_image_path');
                formData.append('pagecontent_id', $('body').data('page-id'));
            },
            init: function() {
                this.on("success", function(file, response) {
                    var type = this.element.dataset['type'];
                    var imagePath = response.imagePath;
                    var parent = dropzone.parent();

                    // If the image type is a background image, set the background to the nearest parent
                    // Else we update the image path
                    if(type == 'background-image') {
                        parent.css('background-image', 'url(' + imagePath + ')');
                    } else {
                        parent.find('img').attr('src', imagePath);
                    }

                });
            },
            uploadMultiple: false,
            acceptedFiles: '.jpg, .jpeg, .png, .svg'
    });

Html snippet (where type is background image):

<section class="intro-section" style="background-image: url({{ $content->header_image_path }})">
            <div class="image-upload" data-type="background-image"></div>

Html snippet (where type is a regular image):

 <div class="content-block-image">
      <img src="{{ $content->content_block_two_image }}" alt="star-icon">
       <div class="image-upload"></div>
</div>          
0 likes
9 replies
noeldiaz's avatar

@Reached not sure if this is anything, but I see that you are attaching your dropzone using the .image-upload class? If that is the case, and both elements are on the page, then they both would get targeted by the dropzone right?

Maybe this is a case where you will need to call the javascript twice for the two elements using ID so that they are unique? Or maybe modify the code so that you can read some unique element from each snippet so that your code can determine if it is one or the other?

EDIT: I see now that you use the data-type="background-image" to switch between both... Probably never-mind what I wrote. :)

Reached's avatar

Hi @noeldiaz ,

Thanks for replying :)

The reason im using the same class, is because I will have more than a few dropzones on my page, so i dont want to repeat my JS too much if I can avoid it :)

noeldiaz's avatar

@Reached sounds logical. I had a similar problem placing multiple google maps on a page a while ago. Your comment made me look how I solved it. I guess I never really did but I ended up cheating. I also didn't want to repeat the code, so I ended up placing the JS code in a partial and then passing it the parameters I needed to make it work:

@section('scripts')
    @include('partials.googlemap', [
        'latitude' => $data['latitude'],
        'longitude' => $data['longitude']
    ])
@stop

Looking at the page I use that partial in multiple places to make maps, and that way I only have 1 place for the JS code. I also see I did something similar on another part of the page, where I had multiple bootstrap-multiselect drop-downs and I got tired of writing the code over and over and ended up doing this:

@section('scripts')
    <script type="text/javascript">
        $(function() {
            @include('partials.multiselect', ['element' => 'completeStatus', 'label' => 'Statuses'])
            @include('partials.multiselect', ['element' => 'inspectionType', 'label' => 'Types'])
        });
    </script>
@stop

There I pass the element name too so it binds to the right one. That way I can include as many as possible on same page but just have 1 JS code.

Reached's avatar

Hi @noeldiaz,

Cool solution! Ill try to see if I can use something similar, I guess my biggest issue is that I dont know how to reference to the right parent from within the script... Oh well, I'll figure it out eventually :)

Reached's avatar

Hi guys,

Instead of creating a new thread for this, I've decided to redescribe the old problem a bit better maybe:

I have some dynamic items on my page, for each of these items I need to create a dropzone. How can I access the parent of each of these dropzones?

I have the following code which works, but the two dropzones are linked together, so if I upload the image in one of them, it will be shown in the other aswell (it does not persist in the backend, but on the client it gets updated with the same image :/)

var serviceBlockUploadImage = $(".service-block-upload").dropzone({
    url: "/upload-service-image",
    maxFiles: 1,
    paramName: 'photo',
    addRemoveLinks: true,
    sending: function(file, xhr, formData) {
        var self = serviceBlockUploadImage;

        // Get the id from the dropzone itself
        var idVal = self.data('id');
        var imageName = 'service_block_image'

        // Append this to the request
        formData.append('id', idVal);
        formData.append('_token', $('meta[name="_token"]').attr('content'));
        formData.append('name', imageName);
        formData.append('pagecontent_id', $('body').data('page-id'));

    },
    init: function() {
        this.on("success", function(file, response) {
            var self = serviceBlockUploadImage;
            var imagePath = response.imagePath;
            var parent = self.parent();

            // If the image type is a background image, set the background to the nearest parent
            // Else we update the image path
            parent.find('img').attr('src', imagePath);

        });
    },
    uploadMultiple: false,
    acceptedFiles: '.jpg, .jpeg, .png, .svg'
});
Swaz's avatar

So it sounds like it's just a problem with your success function. Could it be as simple as using .closest() to traverse up the DOM tree?

Something like:

$('.service-block-upload')
    .closest('.parent-class')
    .find('img')
    .attr('src', imagePath);
gabrielmellace's avatar

I runned into a similar situation, what i did is this:

$(".addImagen i").click(function() { $(this).parent().click();

});

Dropzone.autoDiscover = false;
$(".addImagen").each(function() {
     
     var type= $(this).data('type');

        $(this).dropzone(
             {
        url: base_url+'propiedades/uploadDocumentos/'+type,
        autoProcessQueue: true,
        createImageThumbnails:false,
        uploadMultiple: false,
        parallelUploads: 5,
        maxFiles: 5,
        maxFilesize: 10,
        acceptedFiles: 'image/*',
        addedfile: function(file) { console.log(file); },
        
        init: function() {
            dzClosure = this; // Makes sure that 'this' is understood inside the functions below.
            this.on("success", function(file, response) {
                var obj = jQuery.parseJSON( response );
                
                if(obj.result==0) {
                    notify("Error en la carga",obj.errorMsg,'error');
                    this.removeFile(file);
                }
                else {
                //$(file.previewTemplate).html("");
               
              }
            });
            
            
    
        }
    });
});
Reached's avatar
Level 11

Hi @gabrielmellace,

Looks like a good solution, I will definitely have that in mind when a refactoring round becomes necessary :)

Please or to participate in this conversation.