Home > Enterprise >  How can I set dynamically created ul elements to input a unique parameter into a function?
How can I set dynamically created ul elements to input a unique parameter into a function?

Time:12-24

I used a function which dynamically creates ul elements with unique ids. I need the elements to be able to execute a function, and for the code to know which element executed the function. I've written some pseudo-code below to illustrate:

<ul id = "topic1" onclick = "getReleventLinks(1)"> element1 </ul>
<ul id = "topic2" onclick = "getReleventLinks(2)"> element2 </ul>
<ul id = "topic3" onclick = "getReleventLinks(3)"> element3 </ul>

getReleventLinks(x){
 (gets links with topic x);
}

I have no problem embedding the function upon creating these elements, but I cannot figure out a way for the code to know which ul element executed the function. I just need the ul element's id passed in. The function will perform xml request that returns hyperlinks on the topic passed into the function.

Sorry for the pseudo-code. The actual code in its entirety is quite large and I felt this was an easier way to explain the concept. I am suspecting it may not be possible, and an alternative method would also be welcome.

Thank You

CodePudding user response:

    <ul id="topic1">
      element1
    </ul>
    <ul id="topic2">
      element2
    </ul>
    <ul id="topic3">
      element3
    </ul>
    <script>
    // First way:
    // You can query for all elements that have an id that starts with topic
    // and then add an event listener to each one that can depict which element was clicked
    // based off the event's currentTarget property.
    // https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget
        // Query elements that have a tag name ul and convert the node list
        // into an array
        const ulElements = Array.from(document.querySelectorAll('ul'))

        // Grab only the elements that have an id that starts with topic
        const elementsWithTopicID = ulElements.filter(element => element.id.startsWith('topic'))

        function onClick(event) {
            console.log(event.currentTarget)
        }
        // Add the same event listener to each element
        elementsWithTopicID.forEach(element => element.addEventListener('click', onClick))
    
    // Second Way:
    // This route is a bit more confusing but much more efficient in my opinion
    // Add an event listener on the body and use event bubbling to handle the event

    function onBodyClick(event) {
        const element = event.target
        // A return guard to avoid handling elements that do not have ids
        // that start with topic
        if (!element.id.startsWith('topic')) return;
        console.log(element)
    }
    // When you add the listener to the body, you can handle all click events
    // on the children of the body element
    // https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_bubbling_and_capture
    document.body.addEventListener('click', onBodyClick)
    </script>

CodePudding user response:

Clicks pass an event object to the functions that handle that event. That event object has a target property that is the HTML element that fired that event.

But to use that, you can't pass your functions as strings. You shouldn't anyway, it's a bad practice. Instead, bind the click handlers to the elements, and pass in a reference to a function as the handler. Then the function will be called with the event as the first argument.

Working example:

function getReleventLinks(event){
   console.log(event.target.id)
}

// 'ul' here is whatever CSS selector targets your list
document.querySelectorAll('ul').forEach(ul => {
  ul.addEventListener('click', getReleventLinks);
})
<ul id = "topic1"> element1 </ul>
<ul id = "topic2"> element2 </ul>
<ul id = "topic3"> element3 </ul>

CodePudding user response:

You can use a function for all of them, without passing id, just use this keyword and get element's id for your xmlrequest

  • Related