Howzieky Howzieky - 1 month ago 8
HTML Question

Adding to innerHTML of document.body causes jQuery .on() to not find its target

So I have some dynamically generated HTML stuff. If you click a button, it adds some html that has another button, and you can add that other html several times, generating several copies of it. This is all inside of a

<form>
tag, so I need to use
e.preventDefault()
on each button to prevent javascript from trying to submit the data. Each button also has its own code for
onclick
. There's a problem with javascript-added click events on newly generated content however. If I have
<button class="myBtn"></button>
, then in javascript I have
$(".myBtn").click(...)
, that will work just fine, but only for buttons that already exist when the javascript code is run, meaning newly generated buttons won't have the event attached. The solution to that problem is found here.

Now we come to the real issue. That all works perfectly, but only until I add to
document.body.innerHTML
. As soon as I execute the line
document.body.innerHTML += "Text"
, the code from the link above no longer executes when the generated button is clicked.

I have an example here: https://jsfiddle.net/6hvgatLy/1/

Answer

You are re-writing the whole body innerHTML which will remove all event listeners

Use append() instead

Change

$("#deadlyBtn").click(function(e){
    e.preventDefault(); 
    document.body.innerHTML += "Now try clicking [Add new Input]"
})

To

$("#deadlyBtn").click(function(e){
    e.preventDefault(); 
    $('body').append("Now try clicking [Add new Input]")
})

DEMO

Alternatively you can change your event delegation to an asset that isn't being overwritten like body or document

$(document).on("click", ".formDiv .innerContainer .innerBtn", function(e){
    e.preventDefault()
  $(this).before($('<input type="text" placeholder="Textbox"/>'))
})