Consistent value displayed by addEventListener for each event

Hey everyone, I've been experimenting with different solutions for a few hours now but I'm still stuck on this problem. I have a function that takes JSON as input -

I can create an 'a' element: CHECK I can set all the element properties like 'href': CHECK I can append 'a' with required element tags: CHECK But I am unable to set the

a.addEventListener("click", function () { alert("clicked - " + a.id) }, false);
Every time I click on any href, it displays the last value

function setTags(tagsJson) {

    var obj = JSON.parse(tagsJson); 
    var a = null;
    var linkText = null; 
    for (var i = 0; i < obj.length; i++) {
        if (typeof (obj[i].Tag_name) === 'undefined' || obj[i].Tag_name === null) {
           // DO NOTHING
        }
        else
        {   a = document.createElement('a');
            linkText = document.createTextNode(obj[i].Tag_name);
            a.appendChild(linkText);            
            a.href = "#";               
            a.textContent = obj[i].Tag_name;
            a.className = "badge badge-success";                                      
            document.getElementById("tags").appendChild(a);

          // THE ISSUE LIES HERE
            a.addEventListener("click", function () { alert("clicked - " + a.textContent) }, false); 

       }
     }
}

For example, if the JSON contains the following values

{\"Tag_id\":12,\"Tag_name\":\"Aston Martin\"},{\"Tag_id\":13,\"Tag_name\":\"Cars\"}]"}

It should display unique text in 'textContent' such as 'Aston Martin', 'Aston' and 'Cars' but when clicking on any item, the alert only shows Cars even though the link's text displays the correct values.

https://i.sstatic.net/OiwO2.png

Based on the screenshot above, the text values seem fine, but the addEventListener only displays the last value on CLICK

I believe there is something I am not grasping about addEventListener?

How can I resolve this issue?

Cheers

Answer №1

Swap out a.textContent for this.textContent

a.addEventListener("click", function () { alert("clicked - " + this.textContent) }, false); 

At the point when this event handler is triggered, the for-loop has already completed its iterations until i < obj.length condition is met, causing a to always be the last one.

Answer №2

Upon clicking the item, the function will be triggered, retrieving the variable a which is defined outside of the for loop. The value of a will hold the last item from the loop.

To improve the functionality, consider utilizing the current context within the function by referencing this.

a.addEventListener("click", function () { alert("clicked - " + this.textContent) }, false); 

Answer №3

The reason behind this issue is related to the way the alert function is written:

a.addEventListener("click", function(){
    alert("clicked - " + a.textContent);  // <---- THIS LINE
}, false); 

When using a.textContent in the code snippet above, it will retrieve the value of textContent from the element a.

In your current setup, the value of a is being updated in each loop iteration. Consequently, when the function references a, it will always use the value of a from the last loop. Hence, only the last value of a will be displayed.

To resolve this issue, you have two alternative methods to access the a.textContent within the function:

Method One: Utilize event.target

a.addEventListener("click", function(event){
    alert("clicked - " + event.target.textContent);
}, false); 

Method Two: Implement this

a.addEventListener("click", function(){
    alert("clicked - " + this.textContent);
}, false); 

Example demonstrating the solution

var json = "[{\"Tag_id\":12,\"Tag_name\":\"Aston Martin\"},{\"Tag_id\":13,\"Tag_name\":\"Cars\"}]";

setTags(json);

function setTags(tagsJson) {

    var obj = JSON.parse(tagsJson); 
    var a = null;
    var linkText = null; 
    for (var i = 0; i < obj.length; i++) {
        if (typeof obj[i].Tag_name === 'undefined' || obj[i].Tag_name === null) {
           // DO NOTHING
        }
        else
        {   a = document.createElement('a');
            linkText = document.createTextNode(obj[i].Tag_name);
            a.appendChild(linkText);            
            a.href = "#";               
            a.textContent = obj[i].Tag_name;
            a.className = "badge badge-success";                                      
            document.getElementById("tags").appendChild(a);

          // THE SOLUTION LIES HERE
            a.addEventListener("click", function () { alert("clicked - " + this.textContent) }, false); 

       }
     }
}
a {
  display: block;
}
<div id="tags"></div>

Answer №4

This example illustrates a common mistake involving closures.

The issue lies in declaring the variable a outside of both the for loop and the click callback function. This results in a being overwritten during each iteration of the loop. Consequently, whenever the click function is called, a will be assigned the value set during the last iteration of the loop.

Therefore, in this scenario, you will always see:

a.textContent = obj[obj.length - 1].Tag_name;

To correct this behavior and achieve the intended functionality, you should retrieve the <a> element from the click event itself. This can be accomplished as follows:

a.addEventListener("click", function (event) { // Using the event to identify the clicked element
   const a = document.getElementById(event.target.id); // Accessing the clicked element
   alert("clicked - " + a.textContent)
}, false);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

perform the .then() function within a returned promise

Here is my code snippet: function scammer(message) { return new Promise((resolve,reject)=>{ if(condition){ if (condition) { bot.KickMember(params).then((message)=>{ console.log("kicked"); ...

In the realm of asp.net, the OnClick event springs into action after the

My asp button uses OnClientClick to execute a javascript function, and I also want to run OnClick after OnClientClick. However, the OnClick never seems to execute. Despite looking through similar topics on StackOverflow and other websites, I can't see ...

Can text be inserted into an SWF file using ASP.NET or Javascript via an online platform?

I am managing a website that features videos created by a graphic designer who updates and adds new content regularly. I am looking to add dynamic text to these videos after a specific amount of time, such as "Hosted by XXX". However, I am hesitant to ask ...

What is the proper way to bind CoreUI's CSwitch component?

I am trying to incorporate the CSwitch component into a DevExtreme data grid. While the DxSwitch component functions correctly, I am unable to get the CSwitch to work properly. It seems like I might be using the wrong binding. Could that be the issue? < ...

If the element is checked and equal to a specific value, take action

I am trying to hide one of the 3 radio buttons on my page. Although they all have the same class, each button has a different value. I attempted to write code to achieve this, but unfortunately, it is hiding all radio buttons instead of just one. Could s ...

Encountering an error while attempting to add class-constructed objects to an array list in React/NextJs: "Unable to add property 0, as the object is

This function contains the code required to generate rows for display in a Material Ui table. class User { constructor(id, name, email, measured, offset, paidAmount, status, home, misc, plane, transport, partner, isCoupon) { thi ...

Numerous sections with tabs on the webpage

I am in need of incorporating multiple tabbed sections on a single page, but unfortunately they are currently interconnected. When one tab is clicked, it impacts the others. To see this issue in action, you can visit: https://jsfiddle.net/pxpsvoc6/ This ...

The canvas loadFromJson function fails to implement the font-family property

I have implemented the following code to display Google font and update the canvas: /* on change of font, load the preview and update the canvas */ $('#font').on('change', function () { $('.font_preview').show ...

Tips for sending a JavaScript object from PHP to AJAX

I've been racking my brain for hours, scouring through countless articles, but I'm still unable to crack this puzzle. Here's the situation: I'm currently tinkering with Chrome extensions and I need to make a server call that will fetch ...

The browser has blocked access to XMLHttpRequest from a specific origin due to the absence of the 'Access-Control-Allow-Origin' header in the requested resource

After developing an Asp.Net Core 3.1 API and deploying it on the server through IIS, everything worked fine when sending GET/POST requests from Postman or a browser. However, I encountered an error with the following code: $.ajax({ type: 'GET' ...

When using React, appending a React Link tag to an existing list item may result in the addition of two objects instead of the desired

Trying to create a loop that checks if an object's date matches with a date on a calendar. If it does, I want to add a React Link tag to the respective li element. The loop logic works well, but the issue is when appending the Link tag using createTex ...

Adjust the appearance of a div according to the input value

When a user inputs the correct value (a number) into an input of type "number," I want a button to appear. I attempted var check=document.getElementById("buttonID").value == "1" followed by an if statement, but it seems I made a mistake somewhere. Here&ap ...

Locate a deeply nested element within an array of objects using a specific string identifier

Trying to search for an object in an array with a matching value as a string can be achieved with the following code snippet. Is there an alternative method to optimize this process without utilizing map? Code: const arr = [{ label: 'A', ...

Comparing react-intl and react-i18next for internationalizing ReactJS applications

I am in the process of developing a multilanguage application using ReactJS. This application will require a custom dictionary for various languages, as well as automatic formatting for date/time, numbers, and currency. After researching, I have come acro ...

Grails 3.1.9 does not support displaying JavaScript

Having trouble getting the datepicker to display using JavaScript <script> $( "#invoiceDate" ).datepicker({ inline: true, dateFormat: "yy-mm-dd", onSelect: function(datetext){ datetext = datetext+" 00:00:00.0" ...

Inform jQuery that the draggable element is in the process of being dragged dynamically

Currently, this issue is a vital component of an ongoing task. Once we can resolve this issue, it will lead to the completion of this and another inquiry. The original objective can be found here: drag marker outside map to html element You can view the ...

Testing the JSON ModelBinding functionality in Nancy was a unit testing priority

Currently, I am experimenting with JSON model binding in NancyFx. The request successfully goes through when tested in the browser; however, I am facing an issue getting the unit test to pass. Upon debugging the test, I discovered that the model returned ...

View JSON-formatted information

After retrieving the necessary data from the database and encoding it as JSON, I then pass it to the view: $json_data = json_encode($x); $search_results['search_results'] = $json_data; $this->load->view('findquestions&apos ...

What is the process for importing an md file in a create-react-app project using JavaScript?

Attempting to execute the blog example provided on Material UI's getting started page. However, encountering an issue with the source code: Inside blog.js import post1 from './blog-post.1.md'; . . . return( <Main>{post1}<Main/> ...

Exploring the contrast: resolve() versus fulfill() in q.js

I'm finding it difficult to understand the distinction between calling a resolver's resolve() as opposed to fulfill(). Both functions and terms "resolve a promise" and "fulfill a promise" are frequently used interchangeably. Can you provide guid ...