我的购物车功能有一个简单的问题。点击“添加到购物车”按钮后,如果它具有相同的产品ID,则会在新行中输出新产品。如果产品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>
&#13;
答案 0 :(得分:2)
因此,目前您的代码设置为在将所有产品添加到产品表时删除所有产品,但是在将它们添加到购物车时不会这样做。所以只需添加它就可以删除购物车表中的所有内容
Array.from(cartsTable.children).slice(1).forEach(entry => cartsTable.removeChild(entry));
但是您当前的代码存在一些小问题,nl:
如果您将产品添加到购物车表中,您只会将数量增加1,但是,产品本身可能会设置更高的数量,因此您可以像这样修复它
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" />
用于产品数量
<input type="number" step="0.01" />
用于价格字段我已经重写了你正在描述的函数,使用我在another question上已经给出的答案,它将根据给定的列和包含数据的数组创建表
在添加相同产品时,它仍然存在不会验证描述/价格差异的问题,但它有助于我提到的所有其他问题。
它可能是一个更长的代码,但是,部分原因是表助手功能可以做很多事情,并且可能对你描述的场景有点过分。但它确实有效,并且使表格创建更加容易;)
// 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>
答案 1 :(得分:0)
已经快两年了...但是解决方案实际上很简单:
首先,尝试在控制台上吐出您的产品名称...该值包含空格! ! !
这意味着购物车无需进行任何处理即可添加原始值,因此匹配名称和价格的条件永远不会为真,因此会重复。
解决方案1(乏味):在添加到购物车之前修剪所有值的空格。
解决方案2(首选):不要在值和HTML标记之间添加任何空格!
"<strong class="item_price">price</strong>"
<!-- "NOT -->
"<strong class="item_price">
price
</strong>"