简体   繁体   中英

Last value gets printed instead of each iteration value in for loop while reading file from JSON and looping through it

In the below example we read from a JSON data and store it in a variable. Then we loop through it to print out the value of each of its iteration.

I have "cartList.innerHTML" which will list out "Edit" 4 times as that is the number of the objects in the array. Like below

Edit

Edit

Edit

Edit

Once you click on the first Edit a modal should open and display the name of the first object, on clicking the second edit the name of the second and so on.

But for some reason the value remains to be the name of the last object for each Edit. How do I get it to print the correct name for each edit.

// Fetch JSON data
function loadJSON(file, callback) {
    var xobj = new XMLHttpRequest();
    xobj.overrideMimeType("application/json");
    xobj.open('GET', file, true); // Refers to JSON file
    xobj.onreadystatechange = function() {
        if (xobj.readyState == 4 && xobj.status == "200") {
            callback(xobj.responseText);
        }
    }
    xobj.send(null);
}

function load() {
    loadJSON("assets/cart.json", function(response) {
        var actual_JSON = JSON.parse(response);
        console.log(actual_JSON);

        var cartList = document.getElementById("cart-products");
        var itemObj = actual_JSON.productsInCart;       
        var itemLength = actual_JSON.productsInCart.length;

        // Loop through JSON data
        for (var i = 0; i < itemLength; i++) {

            (function(i) {
                /* Output Link Element with Edit text & on click
                   display a modal containing current value of iteration */

                cartList.innerHTML += '<div>'+
                                      '<a href="javascript: void(0);" class="btn btn-outline button-edit" data-toggle="modal" data-target=".bs-example-modal-lg">Edit</a>'+
                                      '</div>';

                var editCartModal = document.getElementById("edit-cart");
                editCartModal.innerHTML = itemObj[i].p_name;// Name of the current object

            })(i);              

        // for loop ends here
        }

    })
}
load(); // Loads function on page load

It's because though you are running the following code in an IIFE:

var editCartModal = document.getElementById("edit-cart");
editCartModal.innerHTML = itemObj[i].p_name;// Name of the current object

You're just modifying the same modal ( getElementById() ) four times.

A simple answer to fix this would be adding a data attribute:

for (var i = 0; i < itemLength; i++) {

    (function(i) {
         /* Output Link Element with Edit text & on click
            display a modal containing current value of iteration */

        cartList.innerHTML += '<div>'+
                              '<a href="javascript: void(0);"' +  
                                  'class="btn btn-outline button-edit" data-toggle="modal"' + 
                                  'data-target=".bs-example-modal-lg" data-custom-value="' + i + 
                                  '">Edit</a>'+
                              '</div>';
    })(i);              

    // for loop ends here
}

/* ES5 way*/
/*
var list = document.getElementsByClassName('button-edit');
list.forEach(function(){
    ...
})
*/

[...document.getElementsByClassName('button-edit')].map(function(element){
    element.addEventListener('click', function(e){
        var chosenIdx = this.dataset.customValue;
        var editCartModal = document.getElementById("edit-cart");
        editCartModal.innerHTML = itemObj[chosenIdx].p_name;// Name of the current object
    }, false);
});

This happens because every function inside the for loop begins to execute after the loop ends. It's the same behavior as for callbacks. When you call each (function(i) {})(i) they all go to the end of function call stack, and only after last iteration of the loop they start executing (with the last i value).

I'm curious why do you need an internal inline function at all? Why don't just put this code directly to the loop body?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM