JQuery doesn't work for dynamically created elements

I have looked at other solutions on SO for this problem and none of them seemed to help me. To give you some idea, yesterday I was trying to select all DIVs of a class and store their IDs. See this Now that I have ids, I want to create some new items and include ids and be able to click on those new items. I went to JSFiddle to show you a demo, but the crazy part is there, my code works, but in my app (chrome extension) it doesn't. Even crazier is that I am already injecting jQuery click events in other parts of it with no problem, so I am really confused as to why it is not working in this particular case. Here's the JSFiddlewhich works, but in my application it does nothing on click. Thanks for any help! I'm sorry that you are posting so many (stupid) questions.

HTML:

<div class="HA" id="k2348382383838382133"></div>
<div class="HA" id="k2344444444444444444"></div>
<div class="HA" id="k234543544545454454"></div>
<div class="HA" id="k2346787878778787878"></div>

      

JS:

var HAContainer = document.querySelectorAll('.HA');
var HALength = document.querySelectorAll('.HA').length;

    var id = [];
    var j = 0;

    $('.HA').each(function(){
        id[j++] = $(this).attr('id');
    });

for (var i=0; i<HALength; i++) {

    var HABtn, HABtnImg, HAImgContainer;

    HABtnImg = document.createElement("img");
    HABtnImg.src = ("http://www.freesmileys.org/smileys/smiley-laughing002.gif"); 
    HABtnImg.className = "ha-icon"; 

    HAImgContainer = document.createElement("div");
    HAImgContainer.setAttribute("id", 'HA-'+id[i] + '-container');
    HAImgContainer.appendChild(HABtnImg);

    HABtn = document.createElement("div");
    HABtn.className = 'ha-button';
    HABtn.setAttribute("id", 'HA-container');
    HABtn.appendChild(HAImgContainer);

    HAContainer[i].appendChild(HABtn);
    HAClick(id[i]);

}

function HAClick(id) {

    $('#HA-'+id+'-container').click(function() {
        alert("clicked on ID " + id);
    });
}

      

+3


source to share


3 answers


You have to delegate your event to make it work with dynamically added elements:

$('body').on("click", '#HA-'+id+'-container', function() {
    alert("clicked on ID " + id);
});

      

I noticed something and edited with a better approach:

Edit:

HABtn.setAttribute("id", 'HA-container');

      

To:



HABtn.setAttribute("id", 'HA-'+id[i] + '-inner-container');
HABtn.setAttribute("class", 'HA-container');

      

And instead of:

function HAClick(id) {
    $('#HA-'+id+'-container').click(function() {
        alert("clicked on ID " + id);
    });
}

      

just attach the delegate event:

$('body').on("click", '.HA-container', function() {
    alert("clicked on ID " + $(this).attr('id'));
});

      

+3


source


jsFiddle implicitly picks the javascript you are using to place inside the onload event handler.

enter image description here

As a result, your code is wrapped in an onload event handler and basically looks like this

window.onload = function(){
    //your code here
};

      

The reason it works in the jsFiddle is because the script is executed after the DOM has loaded and can thus interact with elements that are in the DOM. Maybe your chrome extension is not working after the items have been loaded.

It would be smart to wrap your javascript in a document.ready shortcut

$(function(){
    //your code here
});

      



Considering there are still some issues in your code. It's not clear why you need to have this nested div structure, possibly as a result of css styling, but one problem is the duplicate ids. They could probably just be class names (I'm referring to "HA container").

jQuery offers a very simple way to create elements in a constructor that you can use here. This will allow your code to be more orderly and readable.

Alternatively, you can store id

which you are using inside a jQuery object reference of the container element for data using .data('id',value)

. This will also allow you to immediately assign a click event handler inside another function in order to assign it.

jsFiddle Demo

$('.HA').each(function(){
    var btn = $('<div class="ha-button HA-container">');
    var cont = $('<div id="'+this.id+'-container">').data('id',this.id);
    cont.click(function(){ alert("clicked on ID " + $(this).data('id')); });
    var img = $('<img src="http://www.freesmileys.org/smileys/smiley-laughing002.gif" class="ha-icon" />');
    $(this).append(btn.append(cont.append(img)));
});
      

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="HA" id="k2348382383838382133"></div>
<div class="HA" id="k2344444444444444444"></div>
<div class="HA" id="k234543544545454454"></div>
<div class="HA" id="k2346787878778787878"></div>
      

Run codeHide result


+1


source


I would rewrite it a bit to take advantage of jQuery:

for (var i=0; i<HALength; i++) {

    var HABtnImg = $('<img/>')
            .attr('src', 'http://www.freesmileys.org/smileys/smiley-laughing002.gif')
            .addClass('ha-icon');

    var HAImgContainer = $('<div/>')
            .attr('id', 'HA-'+id[i] + '-container')
            .append(HABtnImg);

    var HABtn = $('<div/>')
            .addClass('ha-button')
            .append(HAImgContainer);
            //don't use duplicate ID here

    $(HAContainer[i]).append(HABtn);
}

      

And later attach the event like so:

$(document).on('click', '.ha-button', function(e){
   //your click code here 
   var id = $(this).find('div').attr('id');
   alert("clicked on ID " + id);
});

      

0


source







All Articles