Receiving the term "extend" after triggering the button click event while iterating through a for-in loop

I'm facing a challenge with my JSON structure:

people = [{"id":"0001","title":"Mr","name_first":"Bob","name_last":"Edwards","address1":"2 ford road","address2":null,"address3":null,"town":"Bedford","county":"Bedfordshire","postcode":"Mk16hd","telephone1":"01827485999","telephone2":null,"email":"<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5f3d303d1f3a323e3633713c30">[email protected]</a>"},
{"id":"8003","title":"Mr","name_first":"Joe","name_last":"Bloggs","address1":"186 Bath Road","address2":null,"address3":null,"town":null,"county":null,"postcode":null,"telephone1":"01827485648","telephone2":null,"email":"<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="80eaefe5c0e5ede1e9ecaee3efed">[email protected]</a>"},
{"id":"R005","title":"Mr","name_first":"Foo","name_last":"Bar","address1":null,"address2":null,"address3":null,"town":null,"county":null,"postcode":null,"telephone1":"01827485647","telephone2":null,"email":"<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5f3930301f3a32">[email protected]</a>"}];

Tackling this issue involves looping through the JSON and creating buttons:

for (var key in people) { 
    if (people.hasOwnProperty(key)) {
        var person = people[key];

        var button = document.createElement('button');
        button.innerHTML = '<span class="left-body">Edit</span>';
        button.onclick = function() { editPerson(key); return false; };
    }
}

However, I encounter an unexpected behavior when clicking the buttons:

function editPerson(index) {
    console.log(index);
    return false;
}

My question now is: How can I properly pass the key value of each JSON item into the editPerson() function?

Answer №1

The reason behind this behavior is due to the concept of closure

for (var key in contacts) { 
    if (contacts.hasOwnProperty(key)) {
        var contact = contacts[key];

        var button = document.createElement('button');
        button.innerHTML = '<span class="left-body">Edit</span>';
        button.onclick = (function(key){
            return function() { editContact(key); return false; };
        })(key);
    }
}

Sample: Demo

Answer №2

contacts is an array containing contact information. To loop through the properties of a single contact, you must specify it (e.g. using contact[0]). If you want to iterate through the properties of each contact, you need to loop through them as shown below:

for (var i=0;i<contacts.length;i++) {
    for(var key in contacts[i])

Another issue arises when handling button click events:

button.onclick = function() { editContact(key); return false; };

When you click the button, editContact gets called with the last assigned value of key. To maintain the correct value of key, you can use a closure like this:

(function() {
    var currentKey = key;
    button.onclick = function() { editContact(currentKey); return false; };
(());

Updated Solution: If you only need to iterate through the contacts and do not require support for older versions of Internet Explorer (< 9), you can utilize the following approach utilizing the `forEach` method:

contacts.forEach(function(element, index) {
    var button = document.createElement('button');
    button.innerHTML = '<span class="left-body">Edit</span>';
    button.onclick = function() { editContact(index); return false; };      
});

Answer №3

Each time the button is clicked, the editContact function is triggered with the most recent value assigned to the key. This ensures that the index of the JSON row is maintained and can be used for additional actions.

I implemented it in the following manner so that you can access all keys from your JSON:

function addButtons() {

    for (var key in contacts) {
        if (contacts.hasOwnProperty(key)) {
            var contact = contacts[key];
            var button = document.createElement('button');
            document.body.appendChild(button);
            button.setAttribute('id', key);
            button.innerHTML = '<span class="left-body">Edit</span>';
            button.onclick = function () {
                editContact(this.id);
                return false;
            };
        }
    }
}

function editContact(index) {
    for (var key in contacts[index]) {
        console.log("Key :" + key + " Value:" + contacts[index][key]);
    }
    return false;
}

This is how my HTML code appears:

<body onload="addButtons();"></body>

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

What is the best way to assign a series of radio buttons to an array within an Angular controller's model?

Let's say I have a controller that contains an array property named 'houses'. I want to use ng-repeat to display this array on a table row with a set of radio buttons (true/false, etc.). How can I ensure that selecting any of these radio but ...

Exploring the usefulness of `bind(this)` within a ReactJS constructor

I have a good understanding of the Javascript function bind. However, I'm puzzled by why in the React.js snippet below, this is being bound again to itself. Is this related to the constructor, as this in the constructor can vary depending on how it&ap ...

What is the process for adding a 3D object to a webpage and making it interactive with movement?

Hello, I am new to web development and apologize for my limited English skills. I have a specific challenge that I need help with: How can I create a 3D plane on a web page using HTML5 and make it interactive, such as flying or moving within a designated ...

Combine Immer and NgRx reducer for improved state management

Upon analyzing redux and ngrx, it appears that immer is the preferred library for creating a copy of the state before storing it. In following the example provided by immer, I implemented the following code in my reducer: on(exampleActions.updateExample ...

Implementing the Disabled Attribute on a Dynamically Generated Button Using React

My QWERTY keyboard is dynamically rendered through a component as Bootstrap buttons using bootstrap-react. Each button does not have an ID to avoid relying on IDs in React. When a letter button is clicked, it triggers an onClick event passed as props back ...

How to pinpoint a particular element in a parsed json using Ruby

I have a JSON string that I need to parse using Ruby. The string looks like this : [ { "id": 1, "player_id": "not_this_one\n", "highscore": 23 }, { "id": 2, "player_id&qu ...

Using the Volley library, you can retrieve specific data from a list view by clicking on a particular item

If I click on a particular item in the list view, how can I retrieve specific data using the Volley library? I am currently utilizing the Volley library to populate a list view with images and text. Each item in the list contains an image and accompanying ...

Sort by label using the pipe operator in RxJS with Angular

I have a situation where I am using an observable in my HTML code with the async pipe. I want to sort the observable by the 'label' property, but I'm not sure how to correctly implement this sorting logic within the pipe. The labels can be e ...

Manipulating images separately using the canvas

Currently, I am utilizing an HTML5 canvas to generate a collection of trees alongside their corresponding shadows. My objective is to ensure that each shadow corresponds with the position of a designated light source. While I have successfully drawn each t ...

How can one overcome CORS policies to retrieve the title of a webpage using JavaScript?

As I work on a plugin for Obsidian that expands shortened urls like bit.ly or t.co to their full-length versions in Markdown, I encounter a problem. I need to fetch the page title in order to properly create a Markdown link [title](web link). Unfortunatel ...

Kurento's WebRTC feature is currently experiencing difficulties with recording functionality

Currently, I am attempting to capture video using the Kurento Media Server with nodejs. Following the hello-world example provided here, I connected a recorderEndpoint to the webrtcEndpoint and successfully got everything up and running. However, on the se ...

Interactive image grid with adjustable description field per image upon selection

My goal is to create a grid of images with a single text field below the grid. This text field should display the description of the image that was last clicked. The grid is implemented using floating divs within a main div, as shown in the code snippet be ...

When Mui Select is used with grouping, it automatically selects the first option as the default

When Mui Select with grouping is first rendered, it automatically selects the first option, which may seem strange. const generateOptions = useCallback((options: ISelectOption[]) => { return options.map((opt, ind) => { if ...

Issues arise with selecting text and highlighting it in JavaScript functions

I am currently working on a fun little web application that allows users to select text and highlight it in any color they choose. Here is the progress I have made so far: function replaceSelectedText() { var sel, range; var replacementText, spanT ...

JS templating language inspired by Jinja

I find the django/jinja2 templating languages to be truly exceptional. Their syntax is straightforward yet incredibly flexible. I'm wondering if there is a JavaScript library that offers similar simplicity and versatility, or at least matches their ca ...

Passing variables in Redirect() without exposing them in the URL; a methodical approach

After scouring the depths of the internet, I have been on a quest to figure out how to seamlessly redirect to a new page on my site while discreetly passing a variable without exposing it in the URL like so: www.test.com/?variable=dont.want.this.here I a ...

Changing the color of a face in Three.js

I've been trying to change the color of a face, but I'm having trouble. When I use wireframe, it looks like it's working fine. However, when I don't use it, the face doesn't seem to render properly. var geo = new THREE.Geometry(); ...

What is the best way to display a specific item in Pug rather than its entire collection?

I am currently developing an application utilizing Express, Node, and Pug. Within Express, I have set up an endpoint for GET books/:id. During the middleware function, I retrieve all the books and then proceed to render the view. However, in the view, inst ...

Show HTML content using Bootstrap JS tooltip

My goal is to show HTML content in a tooltip title, but instead, plain text is being displayed. <a href="javascript:void(0);" data-html="true" data-toggle="tooltip1" title="<p><label>package_qty</label> (0 status)</p>">0</ ...

Hide specific content while displaying a certain element

Creating three buttons, each of which hides all content divs and displays a specific one when clicked. For instance, clicking the second button will only show the content from the second div. function toggleContent(id) { var elements = document.getEl ...