0

I created a function to clone input files if the user clicked twice on the choose file button to prevent the field from clearing the previous uploaded images

$(function() {

 // Multiple images preview with JavaScript
var multiImgPreview = function(input, imgPreviewPlaceholder) {

    if (input.files) {
     $("#multipleImageUpload").on("change", function(e) {
        var filesAmount = input.files.length;

        for (i = 0; i < filesAmount; i++) {
            var reader = new FileReader();

            reader.onload = function(event) {
                $($.parseHTML("<span class=\"pip\">" + 
                "<br/><span id=\"remove_icon\">Remove</span>" +
                "<img src=\"" + event.target.result + "\" title=\"" + "\"/>" +
                "</span>")).appendTo(imgPreviewPlaceholder);
 
                $("#remove_icon").click(function(){
                   $(this).parent(".pip").remove();
                 }); 
            }

            reader.readAsDataURL(input.files[i]);
        }
      });
    }
};


$(document).on('click', '#multipleImageUpload', function() {
    
    // add to preview
    multiImgPreview(this, 'div.imgPreview');

    
    //clone
    
    var originalInput = $(this), cloned = originalInput.clone();
    
    // move
    originalInput.attr("id", Date.now());
    originalInput.removeClass('multipleImageUpload');
    originalInput.appendTo($('#multipleFilesPH'));
    
    cloned.attr("id", "multipleImageUpload");
    cloned.insertAfter($('#multipleFilesPH'));

    originalInput = null;
    cloned = null;

});
});  

the issue here is when the user clicks on remove button it only removes the image from the view and the uploaded file is not removed and is sent to the server. any Idea what I'm doing wrong here?

  • `$($.parseHTML("..."))` - the `$.parseHTML()` call is unnecessary. The jQuery constructor will parse the string automatically -> https://api.jquery.com/jQuery/#jQuery2 – Andreas Feb 14 '22 at 16:15
  • 1
    `"
    Remove"` - Ids have to be **unique**
    – Andreas Feb 14 '22 at 16:16
  • [Event binding on dynamically created elements?](https://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements) – Andreas Feb 14 '22 at 16:18
  • @Andreas thank you for the input but the id in the span is not related to the issue here, I want to remove the input cloned in the second function. it has unique ids (date) – yara_jae Feb 14 '22 at 16:28

1 Answers1

0

There are two basic ways to do this.

  1. Use .on() to bind to the dynamic element
  2. Store reference to the object in a Variable and assign click() callback to the object

Here is an example of the latter.

$(function() {

  // Multiple images preview with JavaScript
  var multiImgPreview = function(input, imgPreviewPlaceholder) {

    if (input.files) {
      $("#multipleImageUpload").on("change", function(e) {
        var filesAmount = input.files.length;

        $.each(input.files, function(i, file){
          var reader = new FileReader();

          reader.onload = function(event) {
            var pip = $("<span>", {
              class: "pip"
            }).appendTo(imgPreviewPlaceholder);
            var icon = $("<span>", {
              class: "remove_icon"
            }).html("Remove").insertAfter(pip);
            var img = $("<img>", {
              src: event.target.result,
              title: ""
            }).insertAfter(icon);
            
            icon.click(function() {
              $(this).parent(".pip").remove();
            });
          }

          reader.readAsDataURL(file);
        }
      });
    }
  };

  $(document).on('click', '#multipleImageUpload', function() {

    // add to preview
    multiImgPreview(this, 'div.imgPreview');

    //clone
    var originalInput = $(this),
      cloned = originalInput.clone();

    // move
    originalInput.attr("id", Date.now());
    originalInput.removeClass('multipleImageUpload');
    originalInput.appendTo($('#multipleFilesPH'));

    cloned.attr("id", "multipleImageUpload");
    cloned.insertAfter($('#multipleFilesPH'));

    originalInput = null;
    cloned = null;

  });
});

This uses the jQuery ability to create DOM elements on the fly from the provided string of raw HTML. See More.

If you want to bind a click callback to that specific element, you can store the resulting Object in a variable and use that to bind the event to that object alone.

I switched the attribute to Class as you will likely have more than 1 element with this ID, hence why it would not be Unique from other elements. You might end up with 3 or 4 elements with the same ID.

Twisty
  • 30,304
  • 2
  • 26
  • 45