:hover not working on dynamically added <li>

Viewed 313

In the example below, the "I'm Yellow" <li> turns yellow on hover, but when you enter something into the input and click "Generate Text," the dynamically appended <li> doesn't behave the same on hover.

I've tried selecting the appended li's through class and it still doesn't work. There seems to be something about appended elements that I'm not getting. To spare you some time reading the code I'm pretty sure you only need to look at the .hover function.

    <body>
        <a href="" class="buttn btn btn-secondary">
            <div class="" style="background-color: rgb(0, 0, 0); display: inline;"> Hello</div>
        </a>
        <a href="" class="buttn2">
            <div class="btn" style="background-color: aqua; display: inline;"> Bye</div>
        </a>
        <form class="form-disable">
            <br>
            <input type="text" id="message2">
            <br>
             <button id="myButton" type="submit" disabled>Generate Text</button> 
        </form>
    
        
    
        <script src="https://code.jquery.com/jquery-3.6.0.js"
            integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
        <script src="jQueryDrills.js"></script>
    </body>

<script>    
$(".form-disable").after("<ul class='the-list'><li><h2>Im Yellow</h2></li></ul>");
    
    $("#myButton").click(function(event) {
        let theH2 = document.createElement('h2');
        let theLI = document.createElement('li');
        let $alert = $('#message2').val();
        $(theH2).text($alert);
        $(theLI).append(theH2)
        $(".the-list").append(theLI);
        event.preventDefault();
      })
    
      $(".the-list > li").hover(function(){
        $(this).css("background-color", "yellow");
      },function(){
        $(this).css("background-color", "white");
      }
    
      )
    
    $("#message2").click(function(){
        $("#myButton").removeAttr("disabled");
        // event.preventDefault();
    })
</script>
2 Answers

When you first add the event listener, there was only 1 <li> element, so it only added the event listener to the first <li> element.

Instead, add the event listener to the element specifically after creating it like so:

<body>
  <a href="" class="buttn btn btn-secondary">
    <div class="" style="background-color: rgb(0, 0, 0); display: inline;"> Hello</div>
  </a>
  <a href="" class="buttn2">
    <div class="btn" style="background-color: aqua; display: inline;"> Bye</div>
  </a>
  <form class="form-disable">
    <br>
    <input type="text" id="message2">
    <br>
    <button id="myButton" type="submit" disabled>Generate Text</button>
  </form>



  <script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
  <script src="jQueryDrills.js"></script>
</body>

<script>
  $(".form-disable").after("<ul class='the-list'><li><h2>Im Yellow</h2></li></ul>");

  $("#myButton").click(function(event) {
    let theH2 = document.createElement('h2');
    let theLI = document.createElement('li');
    let $alert = $('#message2').val();
    $(theH2).text($alert);
    $(theLI).append(theH2)
    $(".the-list").append(theLI);
    $(theLI).hover(function() {
        $(this).css("background-color", "yellow");
      }, function() {
        $(this).css("background-color", "white");
      }

    )
    event.preventDefault();
  })

  $(".the-list > li").hover(function() {
      $(this).css("background-color", "yellow");
    }, function() {
      $(this).css("background-color", "white");
    }

  )

  $("#message2").click(function() {
    $("#myButton").removeAttr("disabled");
    // event.preventDefault();
  })
</script>

With CSS it gets so much easier:

li:hover{
  background-color:yellow;
}
<body>
  <a href="" class="buttn btn btn-secondary">
    <div class="" style="background-color: rgb(0, 0, 0); display: inline;"> Hello</div>
  </a>
  <a href="" class="buttn2">
    <div class="btn" style="background-color: aqua; display: inline;"> Bye</div>
  </a>
  <form class="form-disable">
    <br>
    <input type="text" id="message2">
    <br>
    <button id="myButton" type="submit" disabled>Generate Text</button>
  </form>



  <script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
  <script src="jQueryDrills.js"></script>
</body>

<script>
  $(".form-disable").after("<ul class='the-list'><li><h2>Im Yellow</h2></li></ul>");

  $("#myButton").click(function(event) {
    let theH2 = document.createElement('h2');
    let theLI = document.createElement('li');
    let $alert = $('#message2').val();
    $(theH2).text($alert);
    $(theLI).append(theH2)
    $(".the-list").append(theLI);
    event.preventDefault();
  })


  $("#message2").click(function() {
    $("#myButton").removeAttr("disabled");
    // event.preventDefault();
  })
</script>

The $(".the-list > li") elector looks for elements that are already on the page. If you are looking to target dynamically created elements then you you need to break it up by first targeting an element that you know is on the page and then target the dynamically generated element and attach the event type using the JQuery on method.

$(".the-list").on("click", "li", function(){

// do whatever here.

})
Related