Click here to Skip to main content
15,881,803 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more: , +
I want to set a click event for each list like this:

Example 0. use an inline event handlers**

HTML
<ul class="fruits">
    <li class="apple" onclick="show(apple)">Apple</li>
    <li class="orange" onclick="show(orange)">Orange</li>
    <li class="cherry" onclick="show(cherry)">Cherry</li>
    <li class="grape" onclick="show(grape)">Grape</li>
    <li class="kiwi" onclick="show(kiwi)">Kiwi</li>
</ul>


As shown above, Inline event handlers, is simple and intuitive, but it's deprecated. so I will use addEventListener method. However, the latter is many different ways to write and I don't know the best.

Here are a few writing ideas I've come up with.

What I have tried:

Example 1. Get the arguments value from class name or data-attribute.

JavaScript
const fruits = document.querySelectorAll(".fruits> li");

fruits.forEach((fruit) => {
  fruit.addEventListener("click", function () {
    // use the class name for matching with arguments. more option is data-attributes.
    const fruitName = fruit.className;
    show(fruitName);
  });
});


Example 2. Get the arguments value from a list in JS.

JavaScript
const fruitList = ["apple", "orange", "cherry", "grape", "kiwi"];

for (let fruit of fruitList) {
  let fruitElem = document.querySelector(`.fruits> li.${fruit}`);
  fruitElem.addEventListener("click", function(){
      show(fruit)
  });
}


Example 3. Get the arguments value from a list, more complex than EX2 for future management, in JS.

JavaScript
const fruitList = [
    {event: "click", key: "apple", func: show},
    {event: "click", key: "orange", func: show},
    {event: "click", key: "cherry", func: show},
    {event: "click", key: "grape", func: show},
    {event: "click", key: "kiwi", func: show},
]

for (let fruit of fruitList) {
    let fruitElem = document.querySelector(`.fruits> li.${fruit.key}`);
    fruitElem.addEventListener(fruit.event, function(){
        fruit.func(fruit.key);
    });
}


What I would like to ask is:

- Which is the best way to do this (EX0-3)?
- If it was you, how to implement this?


Please teach me.
Posted
Updated 30-Aug-21 22:39pm

1 solution

For something like this, the "best" approach is probably to use event delegation:
https://javascript.info/event-delegation[^]
JavaScript
document.querySelector('.fruits').addEventListener("click", function(event){
   const target = event.target.closest('li');
   show(target.className);
});
This has the advantage that it will also work for new elements added to the list via script after the event handler has been attached.
 
Share this answer
 
Comments
Rin O 31-Aug-21 11:04am    
Thanks to give a solution.

Your solution is better than any example.
However, If I click on a padding area in ul, I catch the following error:
=> Cannot read property 'className' of null

So, I need to add a code to return if the clicked area isn't li element.

document.querySelector('.fruits').addEventListener("click", function(event){
   if (event.target.tagName != 'LI') return;  // add this line.
   const target = event.target.closest('li');
   show(target.className);
});


What do you think about this handling, and if it was you, how to solve this problem?
Richard Deeming 31-Aug-21 11:07am    
That would break if you had sub-elements - for example:
<li class="apple">An item with <b>sub-elements</b></li>

If you click on the bold word, the target will be the <b> element.

Try this instead:
document.querySelector('.fruits').addEventListener("click", function(event){
   const target = event.target.closest('li');
   if (target) { show(target.className); }
});
Rin O 31-Aug-21 11:32am    
It worked fine!! Thank you for letting me know.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900