Search code examples
javascriptnumberslocal-storageaddeventlistener

Issue with Input Type number setting the wrong value with addEventListener (JavaScript)


Im a beginner in JavaScript, it's been almost 10days that I'm stuck with that Issue.

The context is pretty Simple: Im trying to build a cart for an e-shopping website that sell couches. The cart must be saved using the localStorage only, and basically if a couch in a specific color is already in the cart, the addition of an other one, in the same property (same name or id and same color) must only increase the quantity selected without adding an other row in my cart.

When you are on the product page, there are two input to configure : color and quantity.

The exercise seems easy, but the input for the quantity (type ="number") has a strange behavior.

Indeed, the first item to be put in the cart, will act "normally", with a "logical" increase, if you want to put more of it. But as soon as you add an other couch (or the same couch, but in an other color), nothing is going right anymore:

  • the quantity will be listened well, but in the object, it will be doubled first. If I choose a third item to put in the cart it will be multiplied by 4 and then it becomes pretty much anarchic (will put some screenshot)
  • the quantity addition might happend, nerver the less, but it's adding me a new row in my array no matter what....

I hope I have been clear enough, and thanks to you for the consideration.

HTML code:

 <article>
            <div class="item__img">
              <!-- <img src="../images/logo.png" alt="Photographie d'un canapé"> -->
            </div>
            <div class="item__content">

              <div class="item__content__titlePrice">
                <h1 id="title"><!-- Nom du produit --></h1>
                <p>Prix : <span id="price"><!-- 42 --></span>€</p>
              </div>

              <div class="item__content__description">
                <p class="item__content__description__title">Description :</p>
                <p id="description"><!-- Dis enim malesuada risus sapien gravida nulla nisl arcu. --></p>
              </div>

              <div class="item__content__settings">
                <div class="item__content__settings__color">
                  <label for="colors">Choisir une couleur :</label>
                  <select name="color-select" id="colors">
                      <option value="" disabled selected  >"--SVP, choisissez une couleur --" </option>
                      <!-- <option value="vert">vert</option>
                      <option value="blanc">blanc</option> -->
                  </select>
                </div>

                <div class="item__content__settings__quantity">
                  <label for="quantity">Nombre d'article(s) (1-100) :</label>
                  <input type="number" name="itemQuantity" min="1" max="100" value="1" id="quantity">
                </div>
              </div>

              <div class="item__content__addButton">
                <button id="addToCart">Ajouter au panier</button>
              </div>
            </div>
          </article>

JS code (I put some console.log for testing)


// Definition des fonctions de stockage et lecture du panier dans le localStorage
// Functions to set and read the cart in the localStorage

function saveCart(cart){
  localStorage.setItem("cart", JSON.stringify(cart));
}

function getCart(){
  let cart= localStorage.getItem("cart");
  if (cart==null){
    return [];
  }else{
    return JSON.parse(cart);
  } 
}

// FOnction de suppression du panier dans le localStorage, pour phase de test 
// removal function for test
function deleteCart(){
  localStorage.removeItem("cart");
}

// Event lié à l'enregistrement du formulaire et envoi au panier
// Event for saving the item into the cart

const boutonAddToCart= document.querySelector("#addToCart");
const productQuantity=document.querySelector("#quantity");
boutonAddToCart.addEventListener('click', function() {
  
  let product= {
    // id: item._id,
    name:item.name,
    qty:parseInt(productQuantity.value,10),
    color:document.getElementById("colors").value
  };
  // deleteCart();
  
  console.log(product);
  
  let cart=getCart();  
  console.log(cart);
  
  if (cart.length===0){
    cart.push(product);
  }
  
  else{
    for (let i=0; i<cart.length; i++){
      console.log(cart[i]);
      
      if (cart[i].name===product.name && cart[i].color===product.color ){ 
        cart[i].qty+=product.qty;
      }
      else {
        cart.push(product);
      }
    }
    
    console.log(localStorage);
  }
  saveCart(cart);
  
});

First Case: I add the same item in the same color, the console.log of the object matches with the input during the event

Second Case: After adding the first Item, I tried to add the same couch in different color & quantity (the console.log of the object matches with the input during the event

I hope I have been clear enough, and thank yall for the consideration.


Solution

  • This loop is wrong:

        for (let i=0; i<cart.length; i++){
          console.log(cart[i]);
          
          if (cart[i].name===product.name && cart[i].color===product.color ){ 
            cart[i].qty+=product.qty;
          }
          else {
            cart.push(product);
          }
        }
    

    For every item in the cart that isn't the same product and color, it pushes this new item to the cart.

    You should use cart.find() to find the matching item in the cart. If it's not found, push the new item.

    boutonAddToCart.addEventListener('click', function() {
    
      let product = {
        // id: item._id,
        name: item.name,
        qty: parseInt(productQuantity.value, 10),
        color: document.getElementById("colors").value
      };
      // deleteCart();
    
      console.log(product);
    
      let cart = getCart();
      console.log(cart);
    
      let oldProduct = cart.find(i => i.name == product.name && i.color = product.color);
      if (oldProduct) {
        oldProduct.qty += product.qty;
      } else {
        cart.push(product);
      }
    
      saveCart(cart);
    
    });