loading...
Cover image for javascript:  add an event listener to an inexistent element.

javascript: add an event listener to an inexistent element.

abdelazize profile image Abde Lazize ・3 min read

When writing the code for your website or app, manipulating the DOM ( document object model ) is a critical skill you must have, so in this article, we will see how to add an event listener to an inexisted element and also some important tips and tricks to avoid unexpected and weird bugs.
I will be using codepen to better demonstrate the example.
the first codepen example

1-Adding a click event to the future element:

The HTML I’m using in the first example is just a simple button that says Go to login page.

<!DOCTYPE html>
<html>
<head>
<title>DOM manipulation</title>
</head>
<body>

<button class="login">Go to Login page</button>

</body>
</html>
Enter fullscreen mode Exit fullscreen mode

For Javascript, I'm adding an event to the button listening for a click, so when the button is clicked, the event function will clear the DOM and insert a login form.

const body = document.querySelector('body');
const btn = document.querySelector('.login');

btn.addEventListener('click', (e)=>{

  body.innerHTML = '';

  body.insertAdjacentHTML('afterbegin', `
  <form action="#" class="form">
  <input type="email" class="input" placeholder="Email">
  <input type="password" class="input" placeholder="Password">

  <button type="submit" class="submit-btn">Login</button>
  </form>
  `)

})
Enter fullscreen mode Exit fullscreen mode

The future element I'm willing to attach the click event to is the button with class submit-btn, to do so we need to determine the closest and always existing parent (in this example is the body) and attach the click event to it, then we will test if the targeted element has the class submit-btn, if so, I'm going to prevent the form from submitting and just write to the console you are logged in :).

body.addEventListener('click', event => {
  if(event.target.matches(".submit-btn")){
    event.preventDefault()
    console.log("you are logged in :)")  
  }
})
Enter fullscreen mode Exit fullscreen mode

2-Adding a different event to the future element:

What if the event we want to attach is not a click let say it’s a change event, how we are going to implement it?
the second codepen example

The HTML I'm using in this example is a button that says Choose a car.

<!DOCTYPE html>
<html>
<head>
<title>DOM manipulation</title>
</head>
<body>

<button class="btn">Choose a car</button>

</body>
</html>
Enter fullscreen mode Exit fullscreen mode

the javascript I will use in this example is the same but instead of inserting a form, I will insert a select element with cars names as options.

btn.addEventListener('click', (e)=>{

  body.innerHTML = '';

  body.insertAdjacentHTML('afterbegin', `
  <label for="cars">Choose a car:</label>

<select name="cars" id="cars">
  <option value="volvo">Volvo</option>
  <option value="saab">Saab</option>
  <option value="mercedes">Mercedes</option>
  <option value="audi">Audi</option>
</select>
  `)

})
Enter fullscreen mode Exit fullscreen mode

The future element we want to attach the change event to it is the select element, so we will attach a click event to the body (the closest and always existing parent), testing if the targeted element has the ID cars if so, we will add a change event to the select element, in the callback function for the change event I will store the select value in a car variable and write it to the console.

body.addEventListener('click', event => {
  if(event.target.matches('#cars')){
    document.getElementById('cars').addEventListener('change', e => {
      const car = document.getElementById('cars').value;
      console.log(car);
    })
  }
})
Enter fullscreen mode Exit fullscreen mode

It works, BUT WAIT A MINUTE.

At first, it looks like it's working, then when you do it again the event fires multiple times, why is that happening?

The first time I got this error I was about to get crazy, I searched everywhere, I tried all the solutions I found but nothing worked for me, then I started experimenting with my code, and BOOOM I found the solution.

the problem why this is happening is because each time we click the select element a change event gets attached to it because the callback function we are using is anonymous, so the solution is declaring the function with a name and then use it as a callback.

const eventHandler = e => {
      const car = document.getElementById('cars').value;
      console.log(car);
    }

body.addEventListener('click', event => {
  if(event.target.matches('#cars')){
    document.getElementById('cars').addEventListener('change', eventHandler)
  }
})
Enter fullscreen mode Exit fullscreen mode

I suggest experimenting with it in codepen example so you can get a better understanding of what happening. I won't fix it in the example, I want to give you the chance to fix it your self to understand it and memorize it.
thank you for reading this article, I hope you liked it and learned something from it. And please excuse my English.

Discussion

pic
Editor guide