Why do javascript events only work on the first element clicked?

Asked

Viewed 92 times

1

I’m putting together a small system that shows stores from a modal with PHP content. When the element is selected in the main HTML page, it displays a modal with a list of stores that, if they have their name clicked, appears an indication in Google Maps next to it.

The problem is: the code and the function work perfectly for the first element of the main page that is clicked, but for the second and the others, the script does not run. That is, when you click on the element to display the other modes, the stores appear, but the Javascript events do not happen, only happen in the first element.

This is the PHP code that is inside the modal in which the stores are displayed:

<div class="lojas">
  <div class="informacoes_lojas">
   <?php foreach($lojas as $loja):  ?>
   <div class="loja_individual">
    <h3 id="loja<?php echo $loja['codigo']?>"><?php echo $loja['nome']?></h3>
    <p><?php echo $loja['endereco']?></p>
    <p><?php echo $loja['bairro'] . " | " . $loja['cidade'] . " - " . $loja['estado']?></p>
    <p><?php echo "CEP: " . $loja['cep']?></p>
    <p><?php echo "Tel.: " . $loja['telefone']?></p>
   </div>
    <?php endforeach; ?>
  </div>
</div>

This is the javascript function that captures the click in the h3 of one of them and displays a iframe of Google Maps:

const encontraLoja = e => {
    loja = e.target.id;
    codigoLoja = loja.replace(/[a-z]+/,"");

    switch (codigoLoja){
        case "1":
            $mapaGoogle.src = "https://www.google.com/maps/embed?pb=!1m16!1m12!1m3!1d3655.4571578146847!2d-46.7012032354786!3d-23.62379373465189!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!2m1!1sAv.+Roque+Petroni+Jr%2C+1089+-+Lojas+63C+e+63D+-+Piso+T%C3%A9rreo!5e0!3m2!1spt-BR!2sbr!4v1556975644631!5m2!1spt-BR!2sbr";
        break;
(...)->restante do switch
                       } 
}

const $lojas = document.querySelector(".lojas");
$lojas.addEventListener("click", encontraLoja);

Note that during the preparation of the stores all receive an ID, which will depend on the code of the same. It is from this ID that Javascript (in the function) can determine the map and the like.

  • What do you mean "click on H3"? You are assigning the event to the element .lojas and there’s only one element of this in the DOM apparently. Your selector shouldn’t be something like .lojas h3 if the intention is to leave the event in these elements?

  • That element. stores is the set of stores, but each H3 (of a number of stores that may vary) will possess the id that will be captured in store = e.target.id, which will have the code used for the rest of the function.

  • But in the question code there is only one element div.lojas and in your Javascript is just selecting it, because you used querySelector('.lojas'). Please make a [mcve] reproducing the problem.

  • Consider that this div with the stores is already within the modal. I used this selector because there is no way I can declare a store directly (by id) that I don’t even know if it will exist in the DOM, because it will depend on the stores that are in the database. Each click on an element of the main page can generate a modal with stores with different codes, so I search the click in the general field of stores (.stores) and identify the store id that was clicked by target.

1 answer

1


This happens because you are using the method querySelector, which only selects the first element found in the DOM with the selector passed:

const $lojas = document.querySelector(".lojas");

If you want to select all elements that have the selector passed, you should use the method querySelectorAll:

const $lojas = document.querySelectorAll('.lojas')

The point is that this method returns an object NodeList, who does not have the method addEventListener on your prototype. For this, we must iterate on each element of this list and add the Listener event:

document.querySelectorAll('.lojas').forEach(($loja) =>
  $loja.addEventListener('click', (event) => {
    // Do stuff.
  })
)
  • 1

    Thank you so much, man, you saved me!

  • Just for the title of curiosity, another very important detail that I had to change: when this php foreach generates the stores, I needed to identify for the JS which element the stores were being referenced, as well as the map could not have a generic name, because all the elements would have the same box that holds the map. So, using ids and unify with store code and element code also helped and now runs perfectly.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.