0

Question: How do I make my eventListeners on buttons of clones active?

Explanation: I am building a plugin using HTML,CSS and Vanilla Javascript (required, no jquery or other libraries). One of the features is to have multiple addresses for a program of an Organization. Also, an organization can have multiple programs.
Visual:
(simple) Org > Program [Address]
(complex) Org > Program [Address, Address1], Program1 [Address2, Address3]
The button for creating a new address is in the address form itself because it needs to append to the same program it is in.
The problem is I am losing the "add address" button's function on the clones. I know I need to update the Javascript's addEventListeners for the new HTML buttons. I know it is literally just calling the same function over again, but I don't want to create a loop and I feel like that is a bad practice.

Sorry if this is a novice question, I don't have a sr to help me
Code::

var addProgramButton = document.getElementById("cloneAddress")
for (var i = 0; i < addProgramButton.length; i++){
     //code that clones and appends
     // Right now I am just calling the same thing again
     // var addProgramButton = document.getElementById("clone...)
 }

*Thank you for those who contributed. What Is working

// The initial Listener

    var cloner2 = 
 document.getElementsByClassName('cloneProgramDetailsButton')
 for (var i = 0; i < cloner2.length; i++){
   cloner2[i].addEventListener('click', function(e){
    addAddress(e)
 })
 }

 //Function for cloning

function addAddress(event){
  console.log("did this trigger it", event)
   var boxes = document.getElementById("cloneProgramDetails");
          var clone = boxes.cloneNode(true);
          var inputElements = clone.querySelectorAll("input");
                for(var i = 0; i < inputElements.length; i++){
                  inputElements[i].value = '';
                  var nameBuilding = inputElements[i].name.split('_')
                  if(nameBuilding.length > 1){
                    inputElements[i].name = nameBuilding[0] + 
    myTicker + "_" + nameBuilding[1];
                  } else {
                    inputElements[i].name = nameBuilding[0] + 
    myTicker
                  }
                }

       event.originalTarget.parentNode.parentNode.parentNode.appendChild(clone)

   var cloner2 = document.getElementsByClassName('cloneProgramDetailsButton')
  for (var i = 0; i < cloner2.length; i++){
    cloner2[i].addEventListener('click', function(e){
        addAddress(e)
    })
  }
}
Mason SB
  • 167
  • 1
  • 1
  • 10
  • 1
    Use event delegation: https://stackoverflow.com/questions/36121179/event-delegation-pattern-with-addeventlistener-and-nested-elements-in-buttons ... https://stackoverflow.com/questions/9106329/implementing-jquerys-live-binder-with-native-javascript ... and 3:rd in this post use plain js: https://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements – Ason Apr 01 '19 at 17:26
  • 1
    If the above works, let me know. – Ason Apr 01 '19 at 17:26
  • @LGSon I might be misunderstanding. I think my issue is the Listener is finding the clones button. I know if i make that ugly loop it will find it. I actually used eventDelegation and had no idea what it was called on another part. – Mason SB Apr 02 '19 at 15:14
  • @LGSon I tried to update the question accordingly. I really appreciate the information because I had no idea what that was called. – Mason SB Apr 02 '19 at 15:16
  • `document.getElementById("cloneAddress")` this will always return 1 element. Id's need to be unique. So you might have a problem with duplicated id's. Make sure you don't use id's on cloned elements or change the id's when you clone them so that they are unqiue. – Mark Baijens Apr 02 '19 at 15:20
  • @MarkBaijens I use a class on the button, and then which ever one gets click, I apply the function. I'll update the code. Not enough coffee... – Mason SB Apr 02 '19 at 15:24
  • Not sure how that edit made the question any different, or more clear. The solution is event delegation, where you don't need to attach an event on dynamically created elements, instead pick up which were clicked on a container. If not, you need to provide a [mcve] so we can see what it is that doesn't work. – Ason Apr 02 '19 at 15:25
  • @MasonSB As others pointed out, event delegation should be your solution, or copy the event handler too when you clone the element. – Mark Baijens Apr 02 '19 at 15:28
  • @LGSon I updated the question with what I have that is working. I am just updating the listener for the button's class Name. – Mason SB Apr 02 '19 at 15:35
  • The edit still doesn't change the fact that event delegation works. Adding the click handler on the container where all the creation of buttons occurs, and then, using `event.target`, you can detect which button were clicked and call which function you want, just how you do with an element specific listener. – Ason Apr 02 '19 at 15:40

0 Answers0