Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript attach events to elements rendered dynamically

I have 2 files index.html and all.js.

all.js

(function(){
    if (document.getElementById('btn1')){
        document.getElementById("btn1").addEventListener("click", displayMessage);
    }

    function displayMessage(){
        alert("Hi!");
    }
})()

index.html

Example 1: - working example

<button id="btn1">Hit me !</button>
<script type="text/javascript" src="all.js"></script>

Example 2: - not working example

<button id="btn2" onclick="show()">Show</button>
<script type="text/javascript">
    function show(){
        var btn = document.createElement("BUTTON");
            btn.setAttribute("id", "btn1");
            btn.innerHTML = "Hit me !";
        document.getElementById("btn2");
        document.body.insertBefore(btn, btn2);
    }
</script>
<script type="text/javascript" src="all.js"></script>

Description: In the first example btn1 was rendered right away and the event was attached to it. In the second example btn1 is rendered only when you click on btn2 and after that if you click on btn1 nothing will happen.

How can I attach the event to btn1 without changing all.js?

Here is the entire code repository

Note: Don't ask my why I try to do something like this, don't ask me why I am not allowed to change all.js because this example is a simplified one, in my case all.js file contains thousands of lines with lots of events on many elements. JavaScript solution means that I am not allowed to use other external libraries.

UPDATE: Answer acceptance

I got a lot of different answers. Some of you worked harder to solve this issue, some of you worked less but the good thing is that I decided. I got some working solutions but some of them worked for only this particular case without taking in consideration that my real all.js file has 4029 lines of code, some solutions suggested to use event delegation which I agree but unfortunately I can not change my all.js file now. In the end I picked the best solutions, I've also considered who answered first, I've taken into consideration also who put a lot of work into this, etc. Anyways, the solution that I'm gonna implement is a merge between 2 solutions, Aruna's and Vlacav's solution (+ some changes by my self) and here it is:

function show(){
    var btn = document.createElement("BUTTON");
        btn.setAttribute("id", "btn1");
        btn.innerHTML = "Hit me !";
    document.getElementById("btn2");
    document.body.insertBefore(btn, btn2);
    resetJs('all.js');
}

function resetJs(path) {
    var scripts = document.getElementsByTagName('script')
        , newScript = document.createElement("script");

    newScript.src = path + "?timestamp=" + Math.round(new Date().getTime()/1000);   

    for (var i = 0; i < scripts.length; ++i) {      
        var srcUrl = scripts[i].getAttribute('src');
        if (srcUrl && srcUrl.indexOf(path) > -1) {                 
           scripts[i].parentNode.replaceChild(newScript, scripts[i]);
        }           
    }
}

Unfortunately I can't split the reputation and I have to give it to only one of them and I want to give this to Vlacav because he was the first one who posted the the solution that I was searching for and he also did some changes on it when I asked him to do so. I also rated up Aruna's answer because he deserve this.

I've posted the solution on a separate branch here and I also created several other branches on this repo with the other solutions that I received because they might be useful in other situations.

like image 805
paulalexandru Avatar asked Dec 16 '16 19:12

paulalexandru


People also ask

How do you bind a click event to dynamically created elements?

To bind the event handler to dynamically created elements, we will be using Event Delegation. On clicking the new list items, the same action is performed.

How do you add event listeners to dynamically created elements?

To attach event handlers to the dynamically created button, we need to select the button with a class of btn and add an event listener of click . We're saying that onclick of the button, the p tag with a class of moreInfo should display block .

How do you dynamically assign an event listener to a button using JavaScript?

This is a lot simpler than you think, in our function that will create our new element, we need to attach the event handler, and function we want to assign to it, this can be done like so: // Create the new element var li = document. createElement('li'); li. className = 'dynamic-link'; // Class name li.

How do you attach a event to element which should be executed only once?

Approach 1: In this approach, we will be using the jQuery one() method. This method attaches an event to the element with the specified selector. It is named one because the event handler corresponding to the event is only executed once.


1 Answers

Add an onclick attribute to the element btn.

function displayMessage() {
  alert("Hi!");
}

function show() {
  var btn = document.createElement("BUTTON");
  btn.setAttribute("id", "btn1");
  btn.innerHTML = "Hit me !";
  btn.onclick = displayMessage;
  document.getElementById("btn2");
  document.body.insertBefore(btn, btn2);
}
<button id="btn2" onclick="show()">Show</button>
like image 67
Jeanger Avatar answered Oct 05 '22 04:10

Jeanger