0

I have this basic HTML that represents a button, I want to attach a click event, but this button is appendend dinamically to the container through a an ajax function, so because this is not present initialy in the DOM, I'm attaching the event to the container in this way

document.querySelector('#container').addEventListener('click', (e) => {
  
  var t = e.target.classList;
  if( t.contains('button-outer') ) console.log(e.target);
  
});
#container {
  width: 100%;
  height: 100%;
  position: relative;
  text-align: center;
}

.button-outer {
  padding: 15px;
  background-color: orange;
  display: inline-block;
  margin: 0 auto;
  text-align: center;
}

.button-inner{
  font-weight: bold;
  cursor: pointer;
  font-size: 75px;
}
<div id="container">
  <div class="button-outer">
    <div class="button-inner">BUTTON</div>
  </div>
</div>

This works, but obviously only when I'm clicking on on the padding part of the outer div. To fix this I have to change the if statement in a way that it will contains the inner part too, like this:

document.querySelector('#container').addEventListener('click', (e) => {

  var t = e.target.classList;
  if( t.contains('button-outer') || t.contains('button-inner')) console.log(e.target);
  
});

I think that this is a little uncovenient, because sometimes the inner part could have other classes, or could be an icon, a link, it is a little difficoult to create specific statements each time, so question is:

How can I propagate the event starting from outer to all inner elements when the button is dinamically appended?

silvered.dragon
  • 407
  • 1
  • 7
  • 19
  • 1
    `if (e.target.closest('.button-outer'))` should do it –  Aug 31 '22 at 08:08
  • @ChrisG really good! but why this is not working if I put the same condition in a switch statement like this `switch(true){ case t.closest('.button-outer'): console.log(e.target); break; }` it doesn't fires, but with the if statement it's ok – silvered.dragon Aug 31 '22 at 08:43
  • What do you mean "it doesn't fire"? There's just a break; there, the switch statement (which is horrible coding style btw) doesn't really do anything? –  Aug 31 '22 at 08:45
  • @ChrisG I forgot to put the console.log, anyway it doesn't do anything. Obviously I will never use the switch statement in this way, it's just to provide a basic example. Sometimes I have click events attached to something bigger like an ajax table, and I'm using the switch statement to provide different actions for each part of the table(like row helpers etc)so I don't think that is an horrible way. – silvered.dragon Aug 31 '22 at 08:50
  • @ChrisG this can be fixed by adding !! before like this `switch(true){ case !!e.target.closest('.button-outer'): console.log(e.target); break; }` – silvered.dragon Aug 31 '22 at 09:13

1 Answers1

1

You should attach your event handler when the button is created, in your ajax function.

But if you need to do it the way you are doing it, you can use closest(), it will traverse all of the target's parents until it finds your query.

document.querySelector('#container').addEventListener('click', (e) => {
  
  var t = e.target;
  if(t.closest('.button-outer')) console.log(e.target);
  
});
#container {
  width: 100%;
  height: 100%;
  position: relative;
  text-align: center;
}

.button-outer {
  padding: 15px;
  background-color: orange;
  display: inline-block;
  margin: 0 auto;
  text-align: center;
}

.button-inner{
  font-weight: bold;
  cursor: pointer;
  font-size: 75px;
}
<div id="container">
  <div class="button-outer">
    <div class="button-inner">BUTTON</div>
  </div>
</div>
Decelis
  • 66
  • 3
  • really good! but why this is not working if I put the same condition in a switch statement like this `switch(true){ case t.closest('.button-outer'): break; }` it doesn't fires, but with the if statement it's ok – silvered.dragon Aug 31 '22 at 08:42
  • Because for that switch to work, the case has to be true, t.closest('.button-outer') returns an Element, but the if statement parses the result to a boolean, [as specified here.](https://262.ecma-international.org/5.1/#sec-9.2) – Decelis Aug 31 '22 at 08:51
  • I feel so stupid, I never thinked about this difference, anyway I fixed this adding !! before like this `switch(true){ case !!t.closest('.button-outer'): console.log(t); break; }` now is perfect for the real project. thank you – silvered.dragon Aug 31 '22 at 09:12
  • 1
    glad I could help. But I suggest what I said before in my response, attaching the event listener to the button when its created is a far better solution than this one. – Decelis Aug 31 '22 at 12:11