购物车中的商品重复 [英] Duplicate of Product in Shopping Cart

查看:68
本文介绍了购物车中的商品重复的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的购物车功能有一个简单的问题.单击添加到购物车按钮后,如果它具有相同的产品ID,则会在新行中输出新产品.如果具有相同的产品ID,则应仅增加产品的数量.

I have a simple problem in my shopping cart function. After i clicked the add to cart button, if it has the same product ID, it outputs a new product in a new row. It should just increase the product's quantity if it has the same product ID.

const products = [];
const carts = [];
const inputs = {
  id: document.getElementById("productID"),
  desc: document.getElementById("product_desc"),
  qty: document.getElementById("quantity"),
  price: document.getElementById("price")
};
const productsTable = document.getElementById("products-table");
const cartsTable = document.getElementById("carts-table");

function renderProductsTable() {
  // delete all entries
  Array.from(productsTable.children).slice(1).forEach(entry => productsTable.removeChild(entry));
    
    for (product of products) {
      const tr = document.createElement('tr');
      const id = document.createElement('td');
      id.textContent = product.id;
      const desc = document.createElement('td');
      desc.textContent = product.desc;
      const qty = document.createElement('td');
      qty.textContent = product.qty;
      const price = document.createElement('td');
      price.textContent = product.price;
      const action = document.createElement('td');
      const deleteButton = document.createElement('button');
      deleteButton.textContent = 'Delete';
      deleteButton.addEventListener('click', () => removeProduct(product.id))
      const addToCartButton = document.createElement('button');
      addToCartButton.textContent = 'Add to cart';
      addToCartButton.addEventListener('click', () => addCart(product.id));
      action.appendChild(deleteButton);
      action.appendChild(addToCartButton);
      tr.appendChild(id);
      tr.appendChild(desc);
      tr.appendChild(qty);
      tr.appendChild(price);
      tr.appendChild(action);
      productsTable.appendChild(tr);
    }

}

function addProduct() {
  
  const product = {
  id: inputs.id.value,
  desc: inputs.desc.value, 
  qty: Number(inputs.qty.value),
  price: Number(inputs.price.value)
  };

  let existing = products.find(item => item.id === product.id);
  if (existing) {
  existing.qty += product.qty;
  } 
  else {
   products.push(product);
  }
  renderProductsTable();
  document.getElementById('order').reset();
  }



function removeProduct(product_id) {
  const index = products.findIndex(p => p.id === product_id);
  products.splice(index, 1);
  renderProductsTable();
}

function addCart(product_id) {
      const product = products.find(p => p.id === product_id);
      const cartItem = carts.find(c => c.product === product);
      
      if(cartItem) {
        cartItem.qty ++;
      }
      else {
        carts.push(product);
      }
      renderCartTable();
          
}

function renderCartTable() {
  for (cart of carts){
    const tr = document.createElement('tr');
    const id = document.createElement('td');
    id.textContent = cart.id;
    const desc = document.createElement('td');
    desc.textContent = cart.desc;
    const qty = document.createElement('td');
    qty.textContent = cart.qty;
    const price = document.createElement('td');
    price.textContent = cart.price;
    const total = document.createElement('td');
    total.textContent = cart.qty * cart.price
    const action = document.createElement('td');
    const subtractButton = document.createElement('button');
    subtractButton.textContent = 'Subtract Quantity';
    const addButton = document.createElement('button');
    addButton.textContent = 'Add Quantity';
    const removeButton = document.createElement('button');
    removeButton.textContent = 'Remove Item';
    tr.appendChild(id);
    tr.appendChild(desc);
    tr.appendChild(qty);
    tr.appendChild(price);
    tr.appendChild(total);
    tr.appendChild(action);
    cartsTable.appendChild(tr);
  }
}

<!DOCTYPE html>
<html>
<head>
  <title>Shopping Cart ES6</title>
</head>
<body>
  <form name="order" id="order">
    <table>
      <tr>
        <td>
          <label for="productID">Product ID:</label>
        </td>
        <td>
          <input id="productID" name="product" type="text" size="28" required/>
        </td>
      </tr>
      <tr>
          <td>
              <label for="product">Product Desc:</label>
          </td>
          <td>
              <input id="product_desc" name="product" type="text" size="28" required/>
          </td>
      </tr>
      <tr>
          <td>
              <label for="quantity">Quantity:</label>
          </td>
          <td>
              <input id="quantity" name="quantity" width="196px" required/>
          </td>
      </tr>
      <tr>
          <td>
              <label for="price">Price:</label>
          </td>
          <td>
              <input id="price" name="price" size="28" required/>
          </td>
      </tr>
  </table>
  <input type="reset" class="resetbtn" value="Reset" />
  <input type="button" id="btnAddProduct" onclick="addProduct();" value="Add New Product" >
</form>
<table border="1|1" id="products-table">
  <tr>
    <th>Product ID</th>
    <th>Product Description</th>
    <th>Quantity</th>
    <th>Price</th>
    <th>Action</th>
  </tr>
</table>
<br />
<h2>Shopping Cart</h2>
<table border="1|1" id="carts-table">
  <tr>
    <th>Product ID</th>
    <th>Product Description</th>
    <th>Quantity</th>
    <th>Price</th>
    <th>Total Amount</th>
    <th>Action</th>
  </tr>
</table>
</body>
<script src="script.js">
</script>
</html>

推荐答案

因此,当前已设置代码,可以在将所有产品添加到产品表时删除所有产品,但是在将它们添加到购物车时不会执行相同的操作.因此,只需添加此内容即可从购物车表格中删除所有内容

So currently your code is setup that you remove all the products when adding them to the product table, however you do not do the same when adding them to the cart. So just adding this would remove everything from your cart table

Array.from(cartsTable.children).slice(1).forEach(entry => cartsTable.removeChild(entry));

不过,您当前的代码nl存在一些小问题:

There are however some minor problems with your current code, nl:

  • 如果您两次添加相同的产品编号,则不会验证价格或说明是否相同
  • 如果您将商品添加到购物车表中,则只会将数量增加1,但是,商品本身的数量可能会更高,因此您可以像这样修改它

  • If you add twice the same product id, you don't validate if the price or the description is the same
  • If you add products to the carts table, you only increase the quantity by 1, however, the product itself may have a higher quantity set, so you can fix it like this

function addCart(product_id) {
  const product = products.find(p => p.id === product_id);
  const cartItem = carts.find(c => c.product === product);

  if(cartItem) {
    cartItem.qty += product.qty;
  }
  else {
    carts.push(product);
  }
  renderCartTable();
}

  • 您可以使用<input type="number" />作为产品数量

  • You could use <input type="number" /> for the product quantity

    我已经使用

    I have rewritten the function you are describing a bit, using an answer I had already given on another question which will create a table based on given columns and an array containing the data

    它仍然存在一个问题,即添加相同产品时,它无法验证描述/价格上的差异,但是对于我提到的所有其他问题都有帮助.

    It still has the problem that it won't validate differences in the description / price when adding the same product, but it helps for all other problems I have mentioned.

    但是,这可能是更长的代码,部分原因是由于表帮助程序功能可以做很多事情,并且对于您所描述的场景而言可能是过大的.但是它确实有效,并且使集成表创建变得更加容易;)

    It might be a bit longer code, however, that is partly due to the table helper function which can do quite some things and might be overkill for the scenario you describe. It does however work, and made it a lot easier to integrate the table creation ;)

    // will reassign when items get removed
    let products = [];
    // will reassign when items get removed
    let cart = [];
    
    function addOrIncrease(item, targetContainer, equality = (i) => i.id) {
      let match = targetContainer.find(i => equality(item) === equality(i));
      if (match) {
        // this could actually be a problem, eg: description and price are not validated
        // you might need to make sure that a warning pops up in case the price is different
        match.qty += item.qty;
      } else {
        // didn't find so it gets added to whichever container
        targetContainer.push(item);
      }
    }
    
    // Gets the value of the elementId or a defaultValue
    function getValue( elementId, defaultValue ) {
      let elem = document.getElementById( elementId );
      if (!elem || !elem.value) {
        return defaultValue;
      }
      return elem.value;
    }
    
    // resets the value for an inputfield
    function resetValue( elementId ) {
      let elem = document.getElementById( elementId );
      elem && (elem.value = null);
    }
    
    // adds a product to the list
    function addProduct() {
      let product = {
        id: getValue('productId', ''),
        description: getValue('productDescription', ''),
        qty: parseInt(getValue('productQty', 1)),
        price: parseFloat(getValue('productPrice', 0))
      };
      if (product.id === '') {
        alert('Please enter a product id');
        return;
      }
      addOrIncrease( product, products );
      resetValue( 'productId' );
      resetValue( 'productDescription' );
      resetValue( 'productQty' );
      resetValue( 'productPrice' );
      renderProducts();
    }
    
    // adds an item to the cart
    function addToCart(itemId) {
      var product = products.find( p => p.id === itemId );
      if (!product) {
        alert('Couldn\'t find product');
        return;
      }
      addOrIncrease( product, cart );
      renderCart();
    }
    
    // removes an item from the cart
    function removeFromCart(itemId) {
      cart = cart.reduce( (current, item) => {
        if (item.id !== itemId) {
          current.push(item);
        }
        return current;
      }, []);
      renderCart();
    }
    
    // removes an item from the products list
    // while simultanously removing it from the shopping cart (as it is no longer in the product list)
    function removeFromProducts(itemId) {
      products = products.reduce( (current, item) => {
        if (item.id !== itemId) {
          current.push(item);
        }
        return current;
      }, []);
      renderProducts();
      // remove it from the cart, as it is no longer in the products list
      removeFromCart(itemId);
    }
    
    // renders the products to the table
    // will re-render the full table each time
    function renderProducts() {
      createTable('products', products, [{
          title: 'id',
          field: 'id',
          class: 'left'
        },
        {
          title: 'description',
          field: 'description',
          class: 'left'
        },
        {
          title: 'quantity',
          field: 'qty',
          class: 'right'
        },
        {
          title: 'price',
          field: 'price',
          class: 'right'
        },
        {
          title: 'total',
          value: (i) => i.price * i.qty,
          class: 'right',
          template: '%0 €'
        },
        {
          title: 'action',
          field: 'id',
          class: 'center',
          template: '<button type="button" onclick="removeFromProducts(\'%0\');">Remove product</button>' +
            '<button type="button" onclick="addToCart(\'%0\');">Add to cart</button>'
        }
      ]);
    }
    
    // renders the cart to the cart table
    // will rerender each time called
    function renderCart() {
      createTable('cart', cart, [{
          title: 'id',
          field: 'id',
          class: 'left'
        },
        {
          title: 'description',
          field: 'description',
          class: 'left'
        },
        {
          title: 'quantity',
          field: 'qty',
          class: 'right'
        },
        {
          title: 'price',
          field: 'price',
          class: 'right'
        },
        {
          title: 'total',
          value: (i) => i.price * i.qty,
          class: 'right',
          template: '%0 €',
          calculateTotal: true
        },
        {
          title: 'action',
          field: 'id',
          class: 'center',
          template: '<button type="button" onclick="removeFromCart(\'%0\');">Remove</button>'
        }
      ]);
    }
    
    /* Helper function to create a table dynamically */
    /* Taken from: https://stackoverflow.com/questions/43924509/creating-an-html-table-using-javascript-and-json/43925208#43925208 */
    function createTable(target, data, columns) {
      // gets the elements required based on id for the target div
      // and creates the table, thead, tbody & tfoot for the table
      let element = document.getElementById(target),
        table = document.createElement('table'),
        thead = document.createElement('thead'),
        header = document.createElement('tr'),
        tbody = document.createElement('tbody'),
        tfoot = document.createElement('tfoot'),
        // totals is used for the totals for the footer
        totals = {};
    
      // creates the header
      for (const column of columns) {
        // and creates the cells in the header, adding title and class
        let cell = document.createElement('td');
        cell.innerHTML = column.title;
        cell.className = column.class;
        header.appendChild(cell);
      }
      thead.appendChild(header);
    
      for (const item of data) {
        // creates the single rows
        let row = document.createElement('tr');
        for (const column of columns) {
          // and for each column creates the cell itself
          let cell = document.createElement('td');
          let value;
          // checks what to display
          if (column.field) {
            // only a property on the data
            value = item[column.field];
          } else if (column.value) {
            // a function with a callback value
            value = column.value(item)
          }
          // if it should calculate totals, it will do so here
          if (column.calculateTotal) {
            // in case the column is unknown, it's initialized as 0
            // warning: all values will be whole numbers
            totals[column.field] = (totals[column.field] || 0) + parseInt( value );
          }
          // if it has a template, we will replace the %0 with value
          // this template function supports only 1 value to be "templated"
          if (column.template) {
            value = column.template.split('%0').join(value);
          }
          // set the cell value
          cell.innerHTML = value;
          // set the class (used to align, for example)
          cell.className = column.class;
          // add cell to row
          row.appendChild(cell);
        }
        // add row to tbody
        tbody.appendChild(row);
      }
      // empty object would mean false, so only if totals needed to be calculated
      // would it create the footer here
      if (totals && data.length > 0) {
        let row = document.createElement('tr');
        for (const column of columns) {
          let cell = document.createElement('td'), value = '';
          if (column.calculateTotal) {
            value = totals[column.field];
            if (column.template) {
              // can still use the row template
              value = column.template.split('%0').join(value);
            }
          }
          cell.innerHTML = value;
          cell.className = column.class;
          row.appendChild( cell );
        }
        tfoot.appendChild( row );
      }
      table.appendChild(thead);
      table.appendChild(tbody);
      table.appendChild(tfoot);
      // clear the target element
      element.innerHTML = '';
      // set the table on the target element
      element.appendChild(table);
    }
    
    // start of the application, create the 2 tables
    // and then it's up to the user
    renderProducts();
    renderCart();

    .left {
      text-align: left;
    }
    .right {
      text-align: right;
    }
    thead tr {
      background-color: #777;
    }
    thead tr td {
      font-weight: bold;
      color: #fff;
    }
    tfoot tr td {
      font-weight: bold;
    }
    table td {
      padding: 5px;
      border-bottom: solid #efefef 1px;
    }
    .fields > div > span:first-child {
      display: inline-block;
      width: 120px;
    }
    .fields > div {
      margin: 5px;
    }

    <div class="fields">
      <div>
        <span>ItemID:</span>
        <span><input type="text" id="productId" placeholder="Item Id" /></span>
      </div>
      <div>
        <span>Description:</span>
        <span><input type="text" id="productDescription" placeholder="Product description" /></span>
      </div>
      <div>
        <span>Quantity:</span>
        <span><input type="number" min="1" id="productQty" placeholder="Quantity" /></span>
      </div>
      <div>
        <span>Price:</span>
        <span><input type="number" min="0" step="0.01" id="productPrice" placeholder="Price" /></span>
      </div>
      <button type="button" onclick="addProduct()">Add to product list</button>
    </div>
    <h1>Products</h1>
    <div id="products">
    </div>
    <h1>Shopping cart</h1>
    <div id="cart">
    </div>

    这篇关于购物车中的商品重复的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆