user2024080 user2024080 - 28 days ago 13
jQuery Question

What is this issue, and how to prevent by jQuery's own way?

I am implementing a append operation using

$.each
- method. the result is funny(getting double the time of elements!). I may have some workaround to fix this.

But I want to understand the real issue here, as well is there a way to fix this using
jQuery
's own way?

Thanks in advance.



var data = ["orange", "apple"];
var temp = function() {
var template = '<dl class="dropdown"><dt> <div class ="dropdownclass" ><span class="hida">Select</span> <span class="multiSel"></span> </div></dt><dd><div class="mutliSelect"><ul><li><input type="checkbox" value="Control" />Control Node</li><li><input type="checkbox" value="Border" />Border Node</li</ul></div></dd></dl>';
return $(template).clone();
}
$(document).ready(function() {
var tr;
var ut
$.each(data, function(i, value) {
tr = $('<tr />', {
id: i + 'id'
});
ut = temp();
ut.addClass('hema' + i).click(function() {
alert($(this).prop('class'));
});
tr.append(ut);
tr.appendTo('tbody'); //getting multple instance!!!
})
})

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<th>title</th>
</tr>
<tbody>

</tbody>
</table>




Answer

The issue is simply because your HTML is invalid. Your tbody must encompass all tr elements. Because you had a tr outside of the tbody the HTML renderer added a second tbody around that - you can see this if you check your original snippet in a DOM inspector. Hence when you appended to tbody the content was duplicated across both elements.

If you fix your HTML, the problem goes away:

var data = ["orange", "apple"];
var temp = function() {
  var template = '<dl class="dropdown"><dt><div class ="dropdownclass" ><span class="hida">Select</span> <span class="multiSel"></span>  </div></dt><dd><div class="mutliSelect"><ul><li><input type="checkbox" value="Control" />Control Node</li><li><input type="checkbox" value="Border" />Border Node</li</ul></div></dd></dl>';
  return $(template);
}

$(document).ready(function() {
  $.each(data, function(i, value) {
    var $tr = $('<tr />', {
      id: i + 'id'
    });
    var $ut = temp().addClass('hema' + i);
    $tr.append($ut).appendTo('tbody');
  })

  $('tbody').on('click', '.dropdown', function() {
    alert($(this).prop('class'));
  });
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
  <tbody>
    <!-- note tbody here -->
    <tr>
      <th>title</th>
    </tr>
  </tbody>
</table>

Note that I made a couple of amendments to your JS logic too; there's no need for the clone() as you're creating a new element anyway, made the var declarations local to the each loop and used a single delegated event handler instead of attaching one to every element in the loop.