How to call init function of Dropzone after every time I click a button using jQuery?

I have a list of similar <div> elements created with a for loop. For each of these <div> elements, I have a button to edit information. Every time this edit button is clicked, a pop-up opens containing a Dropzone box (using the Dropzone library). Now, to load images related to each <div>, I change the input value associated with the image ID using jQuery.

However, I need to read the changed ID from the input and use it in the Dropzone’s init function. The issue is that the Dropzone was created before changing the input value, and during the initial page load, it has an empty value. I want to re-run the Dropzone init function with the same configuration as the previous one after each click on the edit button.

I will now post the code snippets for reference.

HTML File:

@foreach($steps as $step)
    <div class="row card p-3 mb-3 d-flex justify-content-center">
        <div class="col-12 row justify-content-between align-self-center mb-2">
            
            <div class="col-6 p-0">

                <button type="button" class="btn update_step" title="update"
                        data-toggle="modal" data-target="#update_step_modal"
                        step_number="{{$step->number}}"
                        route="{{route('panel.contents.clusters.steps.update', [$content->id, 
                        $cluster->id, $step->id])}}">

                    <span class="mdi mdi-18px mdi-square-edit-outline"></span>
                </button>
              </div>
         </div>

         <div class="col-12 row justify-content-center align-self-center mb-2">
             <p class="col-12 step_description_p">{{$step->description}}</p>

             <div class="col-6 justify-content-center pt-4">
                 <input class="step_cover_id" value="{{$step->cover_id}}" hidden>
                 <img src="{{$step->cover_image}}">
              </div>

         </div>
    </div>      
@endforeach

Modal HTML File:

<div class="modal fade" id="update_step_modal" tabindex="-1" role="dialog" aria- 
      labelledby="update_step_modal" aria-hidden="true" data-keyboard="false" data- 
      backdrop="static">
    <div class="modal-dialog modal-dialog-centered" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>

            <div class="modal-body">
                <div class="col-12 row justify-content-center align-self-center">
                    <form action="" method="POST" id="update_step_form">
                        @method('PATCH')
                        @csrf

                        <textarea name="description" id="update_step_description"></textarea>
                        <input name="cover_id" id="update_step_cover_id" hidden>
                        <input name="video_id" id="update_step_video_id" hidden>

                    </form>
                </div>

                <div class="col-12 row justify-content-center align-self-center mb-2">

                    <div class="col-6" id="update_step_cover_div">
                        <form action="{{url('panel/upload')}}" method="POST" 
                               class="dropzone" id="update_step_cover_form">
                            @csrf
                            <input name="type" value="step_cover" hidden />
                            <input name="content_id" value="{{$content->id}}" hidden />
                            <input name="cluster_id" value="{{$cluster->id}}" hidden />
                            <div class="dz-message" data-dz-message>
                                <span class="m-dropzone__msg-desc">some messages</span>
                            </div>
                        </form>
                    </div>
                </div>

                <div class="d-flex justify-content-center">
                    <button type="button" class="btn" id="step_update_button">
                        <span class="ladda-label">update</span>
                        <span class="ladda-spinner"></span>
                    </button>
                </div>

            </div>
        </div>
    </div>
</div>

JavaScript File:

$('.update_step').on('click', function () {
   let step_number = $(this).attr('step_number')
   let route = $(this).attr('route')

   $('#edited_step_number').text(step_number)
   $('#update_step_form').attr('action', route)

   let parent = $(this).parent().parent().parent();
   let description = parent.find('.step_description_p').text();
   let cover_id = parent.find('.step_cover_id').val();
   let video_id = parent.find('.step_video_id').val();

   $('#update_step_description').val(description).change();
   $('#update_step_cover_id').val(cover_id).change();
   $('#update_step_video_id').val(video_id).change();
});

Dropzone.options.updateStepCoverForm = {
    paramName: "file", 
    uploadMultiple: false,
    acceptedFiles: "image/*,",
    maxFiles: 1,
    headers: {
        'X-CSRF-Token': $('input[name="_token"]').val(),
        'Accept': 'application/json'
    },
    addRemoveLinks: true,
    init: function() {
        let coverDropzone = this;
        let id = $('#update_step_cover_id').val()

        if(id !== ''){
            $.ajax({
                url: '/panel/fetch_file/' + id,
                type: 'get',
                dataType: 'json',
                success: function (response) {
                    var mockFile = {name: response.data.file_name, size: response.data.size};

                    coverDropzone.emit("addedfile", mockFile);
                    coverDropzone.emit("thumbnail", mockFile, response.data.file_path);
                    coverDropzone.emit("complete", mockFile);
                    coverDropzone.options.maxFiles = 0;
                }
            });
        }

        this.on("removedfile", file => {
            let id = $('#update_step_cover_id').val()
            remove_file_function(id, "update_cover")
        });
    },
    accept: function(file, done) {
        done();
    },
    success: function (file, response) {
        $('#update_step_cover_id').val(response.data.id).change();
    },
    error: function (file, response) {
        error_function(file, response)
    }
};

  • Why not use a class name instead of an ID so you can have multiples on the same page?

    – 

  • Because every time this page is loaded, an API is called for each image (in some stages, video) and this increases the page load. This is while with this work, only one or two APE calls may be made. @ChrisBarr

    – 

  • 1

    Maybe reinitialize Dropzone on button click?

    – 

  • How can I do that? @AztecCodes

    – 

  • 1

    @NegarJavadzadeh When you hit the update_step button, once you’ve configured the input values, you remove the previous Dropzone (if it’s there), and then proceed to construct a fresh one. This ensures that the revised input value is picked up by the init function of the new Dropzone.

    – 

Reinitializing Dropzone to Reflect New Input Values

You are dealing with the challenge of updating the Dropzone component after modifying the cover_id input value. The issue here is that the Dropzone component reads the input field value only during its initial setup. If you change the input value later, such as when clicking the update_step button, the Dropzone won’t recognize this change unless you reinitialize it.

  • Dynamically create the Dropzone component: Instead of sticking to Dropzone’s declarative setup via Dropzone.options.updateStepCoverForm, you have the option to dynamically craft and dismantle the Dropzone component as needed.

  • Reinitialize Dropzone on Button click: Each time you press the update_step button once you’ve configured the input values you go ahead and remove the previous Dropzone (if there’s one) and then proceed to generate a fresh one. This approach makes sure that the updated input value is recognized by the newly created Dropzone’s init function.

Updated Code:

// Remove this static configuration
// Dropzone.options.updateStepCoverForm = { ... };

// Variable of the current Dropzone instance
let coverDropzone;

$('.update_step').on('click', function() {
  // TODO: [your previous code here]

  // After setting the new input values reinitialize Dropzone
  initializeDropzone();
});

function initializeDropzone() {
  // If there is already an existing Dropzone instance it gets destroyed
  if (coverDropzone) {
    coverDropzone.destroy();
  }

  // Creates a new Dropzone instance
  coverDropzone = new Dropzone("#update_step_cover_form", {
    paramName: "file",
    uploadMultiple: false,
    acceptedFiles: "image/*,",
    maxFiles: 1,
    headers: {
      'X-CSRF-Token': $('input[name="_token"]').val(),
      'Accept': 'application/json'
    },
    addRemoveLinks: true,
    init: function() {
      // TODO: [put your existing init function code here]
    },
    accept: function(file, done) {
      done();
    },
    success: function(file, response) {
      $('#update_step_cover_id').val(response.data.id).change();
    },
    error: function(file, response) {
      error_function(file, response);
    }
  });
}

initializeDropzone();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Update:

It’s probable that the problem you’re mentioning occurs because, even though you’ve destroyed and reinitialized the Dropzone instance, the DOM elements (i.e., the file previews that were previously fetched) created by the previous instance may still persist.

To address this issue, you can manually eliminate the previews when you destroy the Dropzone instance.

Below is an altered rendition of your code that should handle the clearing of previews:

Your modified code:

$('.update_step').on('click', function () {
    ...
    ... // Your previous code stays here

    // Destroys previous Dropzone instance
    if (Dropzone.instances.length > 0) {
        const dropzoneInstance = Dropzone.forElement("#update_step_cover_form");
        
        // Clears the previews
        dropzoneInstance.removeAllFiles(true);
        
        dropzoneInstance.destroy();
    }

    // Reinitializes the Dropzone with updated configurations
    new Dropzone("#update_step_cover_form", {
        ...
        ... // The rest of your Dropzone configurations stay here
    });
});

Leave a Comment