Adding an Event Listener to Dynamically Created Elements


#1

Hi there,

I’m working on creating a dynamic search page for campgrounds using a JSON file called from gitHub user boondocker.

I have my dynamic search working for updating as I type, but I’d like to be able to click/mouseover each created list item and show more details about it.

Problem is, I can’t seem to properly find the elements after they are created.

Here is my relevant code and the codepen page for the entire project. I’ve tried with vanilla JS and jQuery and haven’t been able to figure it out. The e.target value is returning 0 or undefined on each mouseover.

Would be very appreciative of any help. Thanks.

	// each individual li (class is matches)
const matches = document.querySelectorAll('.matches');
	// mouseover to show more details
$('.matches').on('mouseover', moreDetails);

	function moreDetails(e){
	console.log(`Listening to: ${e.target.value}`);
}

The codepen


#2

I haven’t looked at your code closely but what you have described can be achieved something similar to the code snippet below:

HTML

<div id="app"></div>

JavaScript

const app = document.getElementById('app');

['crimson', 'royalblue', 'turquoise'].forEach((val) => {
  const element = document.createElement('div');
  
  element.textContent = val;
  element.addEventListener('mouseover', () => document.body.style.background = val);
  app.appendChild(element);
});

The key takeaway is that since you are dynamically creating those elements that you want event listeners on, you can simply attach the event listeners right after you have created them, and before you append them to another element.

I hope that helps!


#3

Hi,

I did smoething like this few days ago with jQuery, I was playing with add and remove elements from unordered list.
The way I done it is like this $(".class").on(“click”, function())… and that worked for me. I have that code on another computer I could probably send it later.


#4

https://learn.jquery.com/events/event-delegation/


#5

There is my code that worked, I totaly forgot that I am adding event listener when dynamicly adding new list item.

<!doctype html>
    <html>
        <head>
            <title>Naslov</title>
            <script
                src="https://code.jquery.com/jquery-3.3.1.min.js"
                integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
                crossorigin="anonymous">
            </script>
            <style>
                div{
                    width: 17%;
                }
                li{
                    box-sizing: border-box;
                    border: 2px solid #fff;
                    width: 100%;
                }
                li button:hover{
                    cursor: pointer;
                    transform: scale(1.2, 1.2);
                    transition: 0.5s;
                }
                li .x{
                    color: red;
                    background-color: black;
                    border-radius: 8px;
                    display: inline-block;
                    float: right;
                    text-align: center;
                    vertical-align: center;
                }
            </style>
        </head>
        <body>
            <div>
                    <ul class='lst'>
                        <li class="listItem">First <button class='x'>x</button> </li>
                        <li class="listItem">Second<button class='x'>x</button></li>
                        <li class="listItem">Third<button class='x'>x</button></li>
                    </ul>
                    <input class='inp' type='text' />
                    <button class='btn'>Add item</button>
            </div>
                    <script>
                            let listItems = document.getElementsByTagName('li');
                            let lst = document.querySelector('.lst');
                            let inp = document.querySelector('.inp');
                            let btn = document.querySelector('.btn');
                            let btn2 = '<button class="x">x</button>';

                            function addListItem(){
                                lst.appendChild(document.createElement('li'));
                                let lstChild = lst.lastChild;
                                lstChild.innerHTML = inp.value + btn2;
                                lstChild.className = 'listItem';
                                lstChild.lastChild.addEventListener('click', removeListItem);
                                inp.value = '';
                            }

                            function removeListItem(){
                                 lst.removeChild(this.parentNode);
                            }

                            btn.addEventListener('click', addListItem);
                            $('.listItem .x').on('click', removeListItem);
                    </script>
        </body>
    </html>

#6

Thanks for all the replies. Event delegation was the technique I needed for my instance.

Changing the event listener from the li to the ul and then adding in an if statement in the moreDetails function to only run on each li did the trick.


#7

This is what I was looking for. Cheers.


#8

And it’s the most efficient way to do it. If I created 1000 new Things that needed events, you can see the issue