append li to ul in jquery - onClick stopped working for newly added item

websss
websss used Ask the Experts™
on
I'm facing an issue where i add a new LI to a UL and i'm unable to click it
Based on what i've read its to do with delegates and event handlers

<ul id="SchemeList" class="list-group">

   <li id="71" class="list-group-item">
      <a href="#">namegoeshere</a>
   </li>
</ul>

Open in new window



Here is the click event for the LI
   $('#SchemeList li').on('click', function () {
                alert(this.innerText); 
//...

Open in new window



Here is how i add the LI

<button class="btn btn-success" id="saveNewScheme" type="button" style="">Save New Scheme</button>

Open in new window


  $('#saveNewScheme').on('click', function () {

   var newSchemeId = 11;
   $("#SchemeList").append('<li class="list-group-item" id="' + newSchemeId + '"><a href="#">' + $("#schemeName").val() + '</a></li>');

Open in new window


should this work? or am i doing anything wrong (aside from using numbers for Id's
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Most Valuable Expert 2017
Distinguished Expert 2018
Commented:
This is a classic problem with JavaScript event handling.

Let's look at what you are doing.
$('#SchemeList li').on('click', function () {
                alert(this.innerText);

Open in new window

This code is going to run at page load and it is going to find all li's in the SchemeList and bind a click event handler to them.

Now you add a new li. How is the browser expected to know it must bind a click handler to this element - it was not there when the code above ran - so nothing is going to be bound to it.

I think where the confusion comes in is from a misconception that somehow the $(...).on() is persistent - it is a rule that is always present. The truth is it is not - it runs once and then dies.

So how do we solve the problem of dynamic binding?

You are correct in your use of the .on() function - but incorrect in how you used it.

To bind to dynamic elements we need to bind to a static parent element and then tell jQuery to look for a specific event target when the event fires. How do we do this? By just doing a little rearranging of what you had before
$('#SchemeList').on('click', 'li', function () {
                alert(this.innerText); 
//...

Open in new window

What has changed? We have moved the li from the main selector to the second parameter of the .on(). If you have a look at the api docs for .on() you will see this
.on( events [, selector ] [, data ], handler )

Open in new window

Look at the second parameter - a selector.
What the code above does is it binds to the parent "#SchemeList" - when the click fires jQuery checks to see if the event target is an <li> element - if so the handler fires.

Now you can add as many <li> elements dynamically to your list and they will be "bound" to the event handler.
websssCEO

Author

Commented:
Excellent explanation thanks, works great
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
You are welcome.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial