1

I have a strange situation I ran into with event delegation, the reason being the element is dynamically added to the DOM. A button is clicked to open the modal

To quickly explain this code, there is a modal drawer for desk and mobile and both are being selected here, and the click event is attached to the color swatches inside both of the modals. The modals are dynamically added to the DOM with js

Now the part that is tripping me up is currentTarget is document and if I use e.target, this will be the button that is clicked to open the modal in the first place.

In order to open the modal a button has to be clicked, therefore with event delegation the currentTarget is the document and the target is the button itself, so I really don't know how to attach the event listener to the .swatch in the modal.

$(document).on('click', '.modal-desk__content .swatch, .modal-mobile__content .swatch', e => {
   const $swatch = $(e.currentTarget);
   $('.product-form').find('.swatch[data-value="' + $swatch.data('value') + '"]').click();
   $swatch.closest('.swatches').find('.swatch').removeClass('selected');
   $swatch.addClass('selected');
})
dbzx10299
  • 722
  • 2
  • 14
  • 1
    Use `target`, not `currentTarget`. – Barmar Jun 22 '22 at 20:38
  • https://youmightnotneedjquery.com/#delegate – isherwood Jun 22 '22 at 20:40
  • @Barmar This is the part I am confused about, if I use target, then I will be given the element that the event fired on which is the button to actually open the modal. The question I have is when the modal is opened, how then can I attach the event listener to the .swatch element? Do I need to add an event listener inside of an event listener? – dbzx10299 Jun 22 '22 at 20:42
  • It's almost always wrong to add event listeners inside event listeners. Just use delegation to the `.swatch.selected` class. – Barmar Jun 22 '22 at 20:44
  • I'm probably missing something but if you are using jquery, why not use **$(this)** instead of the target/currentTarget? – imvain2 Jun 22 '22 at 20:57
  • @imvain I am trying to get this refactored to vanilla js – dbzx10299 Jun 22 '22 at 20:59
  • @Barmer Could you give an example, the point I am having a hard time with is the click event is attached to document and a button has to be clicked to open the modal, that means the first click is on the button and clicking in the modal on a swatch would be the second click – dbzx10299 Jun 22 '22 at 21:00
  • Does this answer your question? [Vanilla JavaScript Event Delegation](https://stackoverflow.com/questions/23508221/vanilla-javascript-event-delegation) – gre_gor Jan 04 '23 at 10:19

2 Answers2

3

I was thinking about this all wrong and overthought it. Here is the refactored version for anyone else that runs into this issue

document.addEventListener('click', e => {
   if (e.target.closest('.swatch')) {
      const $swatch = e.target.closest('.swatch')
      document.querySelector(`.product-form .swatch[data-value="${$swatch.dataset.value}"]`).click()

      $swatch.closest('.swatches .swatch').classList.remove('selected')
      $swatch.classList.add('selected')
   }
})
dbzx10299
  • 722
  • 2
  • 14
0

You could always attach the event listener to document on page load then just look for the appropriate class on click.

document.addEventListener("click",function(e){
     if(e.target.classList.contains("swatch")){
          console.log("swatched!");
     }
});

let b = document.createElement("button");
b.innerHTML = "TEST";
b.className = "swatch";
document.body.appendChild(b);
imvain2
  • 15,480
  • 1
  • 16
  • 21