Uncaught ReferenceError: cartRowContents is not defined

Viewed 273

CODE

Here's the code for a function which is triggered when a person clicks on "Add to Cart" button. It creates a row inside the cart using the data from localStorage about the items selected by the user from the menu.

function addItemToCart() {
  var cartRow = document.createElement("div");
  cartRow.classList.add("cart-row");
  var cartItems = document.getElementsByClassName("cart-items")[0];
  var cartItemNames = cartItems.getElementsByClassName("cart-item-title");
  //Putting the data
  var locStore = JSON.parse(localStorage.getItem("selectedProduct"));
  locStore.forEach((item) => {
    var cartRowContents = `
        <div class="cart-item cart-column">
            <img class="cart-item-image" src="${item.image}" width="100" height="100">
            <span class="cart-item-title">${item.title}</span>
            <span class="cart-item-size">"Rs.${item.sizePrice}"</span>
        </div>
        <span class="cart-price cart-column">${item.price}</span>
        <div class="cart-quantity cart-column">
            <input class="cart-quantity-input" type="number" value="1">
            <button class="btn btn-danger" type="button">REMOVE</button>
        </div>`;
  });

  cartRow.innerHTML = cartRowContents;
  cartItems.append(cartRow);
  cartRow
    .getElementsByClassName("btn-danger")[0]
    .addEventListener("click", removeCartItem);
  cartRow
    .getElementsByClassName("cart-quantity-input")[0]
    .addEventListener("change", quantityChanged);
}

ERROR

I'm getting the error

Uncaught ReferenceError: cartRowContents is not defined

I have defined cartRowContents. I also tried defining it using 'let' but the error persisted.
I'm fetching the data from localStorage and rendering it to the UI using above method.
Please help.

3 Answers

Replace

locStore.forEach((item) => {
    var cartRowContents = `
        <div class="cart-item cart-column">
            <img class="cart-item-image" src="${item.image}" width="100" height="100">
            <span class="cart-item-title">${item.title}</span>
            <span class="cart-item-size">"Rs.${item.sizePrice}"</span>
        </div>
        <span class="cart-price cart-column">${item.price}</span>
        <div class="cart-quantity cart-column">
            <input class="cart-quantity-input" type="number" value="1">
            <button class="btn btn-danger" type="button">REMOVE</button>
        </div>`;
  });

With

var cartRowContents = locStore.map((item) => {
    return `
        <div class="cart-item cart-column">
            <img class="cart-item-image" src="${item.image}" width="100" height="100">
            <span class="cart-item-title">${item.title}</span>
            <span class="cart-item-size">"Rs.${item.sizePrice}"</span>
        </div>
        <span class="cart-price cart-column">${item.price}</span>
        <div class="cart-quantity cart-column">
            <input class="cart-quantity-input" type="number" value="1">
            <button class="btn btn-danger" type="button">REMOVE</button>
        </div>`;
  });

Then you have an array with all the HTML, which you can join with this line: cartRowContents = cartRowContents.join("");

The problem is the scope: You are defining cartRowContents only in that arrow function within forEach, and it can only be called inside there

cartRowContents is declared inside a function, so it only "lives" inside the callback function of the forEach.

[1, 2, 3].forEach(() => {
  var functionVariable = "I'm alive!";
});
console.log(functionVariable);

On the contrary, the following would work using a for loop (though not a good algorithm):

for (value in [1, 2, 3]) {
  var loopVariable = "I'm alive!";
}
console.log(loopVariable);

Using a variable outside the block where it was declared is not a good idea. Instead, you could declare the variable before the forEach, assign it inside the forEach and then use it after checking it has a value.

var loopVariable;
for (value in [1, 2, 3]) {
  loopVariable = "I'm alive!";
}
if (loopVariable) {
  console.log(loopVariable);
}

However, that doesn't look right yet because you are declaring a variable in each loop iteration. Do you really need to loop over locStore? Perhaps your intention was collecting an array of all the values, in which case you could do the following:

const cartRowContents = locStore.map((item) => {
  return `
    <div class="cart-item cart-column">
        <img class="cart-item-image" src="${item.image}" width="100" height="100">
        <span class="cart-item-title">${item.title}</span>
        <span class="cart-item-size">"Rs.${item.sizePrice}"</span>
    </div>
    <span class="cart-price cart-column">${item.price}</span>
    <div class="cart-quantity cart-column">
        <input class="cart-quantity-input" type="number" value="1">
        <button class="btn btn-danger" type="button">REMOVE</button>
    </div>`;
});

In this case, cartRowContents will be an array where each element will be the value assigned by each item in locStore.

I am not really sure what you are trying to do within the forEach but the error is occurring because cartRowContents is defined within the scope of the callback parameter of forEach. It is not accessible by the outer scope, you should move it outside.

Related