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.