Search code examples
javascriptjqueryonclick

Click event do not work to child elements of dynamic created element


I'm working with bootstrap-colorpicker in order to fill a color input value with a simple graphic content. In order to give some "tip colors" I tried to append the default bootstrap-colorpicker with some other colors. It looks like this:

Default

With modification

In order to achieve this I added the following code to end of page. It basically let's colorpicker loads by it self and then append the desired div with the elements.

$(document).ready(function() {
  setTimeout(function() {
    $(".colorpicker-color").remove();
    $('<div style="display: block;width:130px;height:100px;/* float: right; */position: absolute;top: 104px;/* overflow-y: scroll; */"><div><small class="text-muted">Sugestões:</small><div style="display: flex;flex-wrap: wrap;padding:5px;height: 60px;overflow-y: scroll;"><i class="fas fa-circle" style="top: 0px;margin:5px;color:#aaa;cursor:pointer" id="color_0" onclick=" alert('im working');"></i></div></div> </div>').insertAfter(".colorpicker-hue");
    $(".colorpicker").css("height","185px");
  }, 500);
});

The problem is that the click event to the fas fa-circle is not working. I place alert("im working"); just for testing proposes. I't won't show up on clicking.

The resulting code after jquery adds the elements it's the following:

[![resulting code][3]][3]

Solution

  • All of the answers have excellent advice for you, but they may have missed the problem. In fact, Ludovico gave you the answer but it was quietly included with his other very useful information so perhaps you missed it.

    You are encountering something called event delegation. That means, items newly added into the DOM do not have click bindings associated with them (even though you defined them in code) because they were not in the DOM when the click events were bound to the appropriate elements.

    (Note that "the DOM" is basically the living webpage as it appears on your screen - with all real-time mods from javascript, etc. So it is more than just the HTML code.)

    Pure JavaScript:

    • Add an event listener to a parent container - or even to the body element. NB: Make sure that you choose an event (e.g. 'click') that bubbles - not all events bubble. For example, the blur event does not bubble (use focusout instead).

    • In the (above-described) event listener, get the value for event.target / e.target / whateverucallit.target - that should be the element that was clicked on.

    Working DEMO:

    const $ = document.querySelector.bind(document);
    $('#myButt').addEventListener('click', myButtClicked);
    $('#injectHereDiv').addEventListener('click', newButtClicked);
    $('#topLevelDiv').addEventListener('focusout', newButtBlur);
    
    function myButtClicked(){
      $('#injectHereDiv').innerHTML = '<button id="newButt">Now Click ME</button>';
    }
    function newButtClicked(e){
      const laId = e.target.id;
      alert(`Ya clicked [#${laId}] - and this alert just blurred that button, so we now use focusout to catch THAT event`);
    }
    function newButtBlur(e){
      const leId = e.target.id;
      $('#injectHereDiv').innerHTML = `The newButtBlur function just fired (when [#${leId}] lost the focus) and replaced the newly-injected button with this text.`;
    }
    <div id="topLevelDiv">
      <div id="midDiv">
        <div id="injectHereDiv"></div>
      </div>
    </div>
    <button id="myButt">Click Me</button>

    jQuery:

    Very simple to solve this, using jQuery.

    Instead of:

    $('#myID').click(function(){
        //your code here
    });
    

    do this instead:

    $(document).on('click', '#myID', function(){
        //your code here
    });
    

    What this does is bind the click event to something that does exist at the time the DOM is rendered (i.e. the "document" object) - and jQuery's .on() method now watches the DOM for anything else being inserted. If any new element matches the specified element, then the click event is bound to that element whenever it appears in the DOM.

    References:

    https://learn.jquery.com/events/event-delegation/

    https://api.jquery.com/on/

    http://jqfundamentals.com/chapter/events