0

I have a function that creates dynamic buttons and assigns them unique id and text values. They're created and rendered just fine on the UI, but I'd like to be able to assign them separate onclick event listeners. The following is the logic in question:

function createLinkButtons(){
      for(var i = 0; i < currentOrder.links.length; i++){
        currentLink = currentOrder.links[i]
        var currentHTML = linksButtonsDiv.innerHTML;
        linksButtonsDiv.innerHTML = currentHTML + 
        `
        <button type="button" id="${currentLink.rel}">${currentLink.rel}</button>
        `
        
        var button = new Object();

        button = document.getElementById(currentLink.rel) //<-- gets overwritten by the next loop iteration
        
        var rel = currentLink.rel;

        //onclick function should receive param argument to know how to proceed accordingly
        button.onclick = function(rel){
          console.log("it workded"); 
        }

      }
    }

Interestingly, I am able to set the onclick event to the LAST button that gets created. This is because the last button that gets created "keeps" the onclick reference. How can I keep all of the previous references to the button alive in memory so that they also react when I click on them?

I've seen other posts in which the dynamically-created buttons are assiged an onclick event dynamically, but the function is just a signature and does not accept a param argument. I need to include a param argument when invoking the onclick event. Is there any way to do this?

Vismark Juarez
  • 613
  • 4
  • 14
  • 21
  • At first, see https://stackoverflow.com/questions/65177040/how-to-assign-onclick-events-to-dynamically-created-buttons-using-javascript , then https://stackoverflow.com/questions/256754/how-to-pass-arguments-to-addeventlistener-listener-function – Teemu Dec 07 '20 at 06:49

2 Answers2

1

Actually you have an issue with your code, because once you create a button, inject it in the DOM and attach an event, then the next iteration of your loop is simply removing it and creating a new instance of the button (with same id).

To fix it, you should not modifying the whole HTML but rather append child dynamically: Initial code:

linksButtonsDiv.innerHTML = currentHTML + 
`<button type="button" id="${currentLink.rel}">${currentLink.rel}</button>`

New Code:

let button= document.createElement("button");
button.setAttribute('id', currentLink.rel);
button.innerHTML = currentLink.rel;
linksButtonsDiv.parentNode.appendChild(button);
function onClick() {
   console.log("it workded");
}
button.addEventListener("click", onClick, false);

PS: It's a detail but this is not the most efficient way to do, it's better to push all your buttons at once in the DOM and then attach events.

Mathieu Seiler
  • 726
  • 8
  • 13
-1

Try using let instead of var

for(let i = 0; i < currentOrder.links.length; i++){
    ...

var is function scoped

let is block scoped

When using var in this instance, all the JQuery inside the loop reads the last defined value for your i variable, which is currentOrder.links.length - 1 -- that's why the last button works

Vardan Betikyan
  • 354
  • 5
  • 20