2

I have a div element whose id attribute is "selectAll". Using jQuery's .clone() method I am cloning that element and changing its id attribute to a new one using jQuery's .prop() method. This procedure of cloning that element and changing its id to a new one is done many times depending on user input. So, now I have one element with id attribute value "selectAll" and many clones of it with changed id.

Within this element with id attribute value "selectAll" is one selection box with class name 'period'. What I want is when the user changes the value in that select box its closest parent id should be displayed in an alert box. Between selection box and 'selectAll' there is no element who has an id attribute.

When the user changes the selection value in the original div element, the alert box displays 'selectAll', which is correct. But the problem is whenever the user changes selection values in a cloned element, the alert box doesn't appear at all.

$("#docsUpload").change(function() {
   $("#multiShow").empty();                 // removes child elements
    var ele = document.getElementById($(this).attr('id'));
    var result = ele.files;
    var ff = result[0];
    $("#ff").html("<strong> File Name : </strong>"+ ff.name);

    for(var x = 0;x< result.length-1;x++){
       var fle = result[x+1];
       $('#multiShow').append("<div class='row'> <div class='col-sm-3'></div> <div class='col-sm-6'><hr>");
       $('#multiShow').append("&nbsp;<strong> File Name : </strong>"+fle.name);
       $('#multiShow').append("</div><div class='col-sm-3'></div></div>");
       $("#selectAll").clone().prop({ id:'thisisid_'+x}).appendTo('#multiShow');
    }
});


$(document).ready(function() {
  $(".static").show(); // always display on page load
  $(".period").on('change', function() { //selection box value changed

    var realId = $(".period").closest("div[id]").attr("id"); //get id
    alert(realId); // display id in alert box (only shows 'selectAll')


    // below code can be ignored
    $('.dateSelector').hide();
    var operation = ' .' + this.value;
    $(operation).show();
  }); // on period change
}); // document ready state
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

 <input type="file" name="docs[]" id="docsUpload" class="" multiple="multiple" required="" />


<div id="selectAll">
        <select name="period" class="period">
          <option value="static" selected="selected">Static</option>
          <option value="monthly">Monthly</option>
          <option value="quaterly">Quaterly</option>
          <option value="semester">Semester</option>
          <option value="yearly">Yearly</option>
          <option value="other">Other</option>
        </select>
 </div>

 <div id="multiShow"> </div>
WeAreRight
  • 885
  • 9
  • 24

2 Answers2

1

When calling .clone(), pass true as the first argument, in order to copy the events and data.

.clone( [withDataAndEvents ][, deepWithDataAndEvents] )

Description: Create a deep copy of the set of matched elements.

Parameters:

withDataAndEvents (default: false)
Type: Boolean
A Boolean indicating whether event handlers should be copied along with the elements. As of jQuery 1.4, element data will be copied as well.

deepWithDataAndEvents (default: value of withDataAndEvents)
Type: Boolean

A Boolean indicating whether event handlers and data for all children of the cloned element should be copied. By default its value matches the first argument's value (which defaults to false).

So change this line:

$("#selectAll").clone().prop({ id:'thisisid_'+x}).appendTo('#multiShow');

to:

$("#selectAll").clone(true).prop({ id:'thisisid_'+x}).appendTo('#multiShow');

Update - finding the correct container div (with id attribute):

Then when finding the id of the div above the select list, accept the changeEvent argument in the event handler callback and traverse the DOM (using .closest()) to find the div with the id attribute. The current code just takes the first element with class name period and finds the closes div element with an id attribute. It needs to be dependent on the target element of the event.

So change this event handler:

$(".period").on('change', function() { //selection box value changed
    var realId = $(".period").closest("div[id]").attr("id"); //get id

like this:

$(".period").on('change', function(changeEvent) { //selection box value changed
    var realId = $(changeEvent.target).closest("div[id]").attr("id"); //get id

$("#docsUpload").change(function() {
   $("#multiShow").empty();                 // removes child elements
    var ele = document.getElementById($(this).attr('id'));
    var result = ele.files;
    var ff = result[0];
    $("#ff").html("<strong> File Name : </strong>"+ ff.name);

    for(var x = 0;x< result.length-1;x++){
       var fle = result[x+1];
       $('#multiShow').append("<div class='row'> <div class='col-sm-3'></div> <div class='col-sm-6'><hr>");
       $('#multiShow').append("&nbsp;<strong> File Name : </strong>"+fle.name);
       $('#multiShow').append("</div><div class='col-sm-3'></div></div>");
       $("#selectAll").clone(true).prop({ id:'thisisid_'+x}).appendTo('#multiShow');
    }
});


$(document).ready(function() {
  $(".static").show(); // always display on page load
  $(".period").on('change', function(changeEvent) { //selection box value changed

    var realId = $(changeEvent.target).closest("div[id]").attr("id"); //get id
    alert(realId); // display id in alert box (only shows 'selectAll')


    // below code can be ignored
    $('.dateSelector').hide();
    var operation = ' .' + this.value;
    $(operation).show();
  }); // on period change
}); // document ready state
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="selectAll">

    <input type="file" name="docs[]" id="docsUpload" class="" multiple="multiple" required="" />

        <select name="period" class="period">
          <option value="static" selected="selected">Static</option>
          <option value="monthly">Monthly</option>
          <option value="quaterly">Quaterly</option>
          <option value="semester">Semester</option>
          <option value="yearly">Yearly</option>
          <option value="other">Other</option>
        </select>
      </div>


  <div id="multiShow"> </div>
Sᴀᴍ Onᴇᴌᴀ
  • 8,218
  • 8
  • 36
  • 58
  • I tried that, now alert box showing but they all contains 'selectAll' instead of new id. – WeAreRight Jan 30 '17 at 07:10
  • Thank you , it is working now. Can you explain what was wrong with my code? it will be great help to my understanding. – WeAreRight Jan 30 '17 at 07:19
  • I expanded the explanation about the change event callback and selecting the div of the select list that was changed, not just the first one with class *period*. – Sᴀᴍ Onᴇᴌᴀ Jan 30 '17 at 07:27
1

Clone function doesn't clone element event listeners and element data. You have to use:

element.clone(true, true);

More info here: https://api.jquery.com/clone/

pzworks
  • 165
  • 2
  • 8
  • if i do clone(true,true) then alert box for cloned elements is coming , but they showing id as 'selectAll' why is that? – WeAreRight Jan 30 '17 at 07:01