Reputation: 79
What my program is supposed to do is function as a shopping cart. On the input boxes,the user enters the productCode
and the quantity
and when they click on the button
on the form, the program creates a dynamic list of the product added, quantity ordered, total of the quantity while updating the total
each time. The error I am having is my function is not displaying the proper output. Forgive me and my inexperience but I chose to use the map()
and push()
in order as I wasn't sure how else to code this. Any help would be appreciated.
Current/Wrong Output
Correct/Desired Output
Current Code
let purchases = []
//function to create shopping cart
function createList() {
let products = ["Winter Hat", "Warm Coat", +"Gloves"];
let prices = [27.50, 160.23, 23.99];
let productCode = document.getElementById("productCode").value;
let quantity = document.getElementById("quantity").value;
let message = " Product Code or Quantity invalid. Enter values from list above.";
// message to alert if code is invalid
if (productCode < 1 || productCode > 3 || quantity < 1) {
alert(message);
}
purchases.push({
product: products[productCode - 1],
quantity: quantity,
total: "Total Price: $" + prices[productCode - 1] * quantity
});
// appends list to
let list = document.getElementById("list");
// cals for every item
list.innerHTML = purchases.map(p => {
return "<li>" + p.product + " (Quantity: " + p.quantity + ") Cost: " + p.total + "</li>";
}).join("");
//
document.getElementById("results").innerText = purchases.reduce((a, c) => {
return a + c.total;
}, 0);
}
<body>
<h1> Point of Sale System </h1>
<form id="myForm">
This is the point of sale program for a store selling winter clothes.
<ul>
<li>Product Code 1: “Winter Hat” for $27.50</li>
<li>Product Code 2: “Warm Coat” for $160.23</li>
<li>Product Code 3: “Gloves” for $32.99</li>
</ul>
<table>
<tr>
<td>Enter the Product Code:</td>
<!--Input field for productCode-->
<td><input id="productCode" type="number" value=""></td>
</tr>
<tr>
<td>Enter the Quantity:</td>
<!--Input field for quantity-->
<td><input id="quantity" type="number" value=""></td>
</tr>
</table>
<input type="button" value="Add this item to purchase order" onclick="createList()">
<ul id="list"> </ul>
<div id="results"></div>
</form>
</body>
Upvotes: 0
Views: 153
Reputation: 4937
The problem is due to 2 issues:
typo : presence of + in front of the word "Gloves"
Value of 'total' containing a string, which in turn is causing new values to be appended instead of being added.
total: "Total Price: $" + prices[productCode - 1] * quantity
The problem can be fixed by these 2 steps:
Remove the typo (+ character) from products array definition
Initialise a variable named total
to 0 and add new values to it.
Working solution:
<!DOCTYPE HTML>
<html lang="en-GB">
<head>
<title>Products demo</title>
</head>
<body>
<h1> Point of Sale System </h1>
<form id="myForm">
This is the point of sale program for a store selling winter clothes.
<ul>
<li>Product Code 1: “Winter Hat” for $27.50</li>
<li>Product Code 2: “Warm Coat” for $160.23</li>
<li>Product Code 3: “Gloves” for $32.99</li>
</ul>
<table>
<tr>
<td>Enter the Product Code:</td>
<!--Input field for productCode-->
<td><input id="productCode" type="number" value=""></td>
</tr>
<tr>
<td>Enter the Quantity:</td>
<!--Input field for quantity-->
<td><input id="quantity" type="number" value=""></td>
</tr>
</table>
<input type="button" value="Add this item to purchase order" onclick="createList()">
<ul id="list"> </ul>
<div id="results"></div>
</form>
<script>
let purchases = []
var total = 0.0
//function to create shopping cart
function createList() {
let products = ["Winter Hat", "Warm Coat", "Gloves"];
let prices = [27.50, 160.23, 23.99];
let productCode = document.getElementById("productCode").value;
let quantity = document.getElementById("quantity").value;
let message = " Product Code or Quantity invalid. Enter values from list above.";
// message to alert if code is invalid
if (productCode < 1 || productCode > 3 || quantity < 1) {
alert(message);
}
total += (prices[productCode - 1] * quantity)
purchases.push({
product: products[productCode - 1],
quantity: quantity,
total: "Total Price: $ " + total
});
// appends list to
let list = document.getElementById("list");
// cals for every item
list.innerHTML = purchases.map(p => {
return "<li>" + p.product + " (Quantity: " + p.quantity + ") Cost: " + p.total + "</li>";
}).join("");
document.getElementById("results").innerText = purchases.reduce((a, c) => {
return a + c.total;
}, 0);
}
</script>
</body>
</html>
Upvotes: 0
Reputation: 17
I've made few changes that I would like for you to evaluate:
Remove the text from the products object, that means to keep the total property only the price of the operation, as this:
purchases.push({
product: products[productCode - 1],
quantity: quantity,
total: prices[productCode - 1] * quantity
});
Add the label Total Price: $"
to the inner text assignment:
document.getElementById("results").innerText = "Total Price: $" + purchases.reduce((a, c) => {
return a + c.total;
}, 0);
That should keep clean the output, in summary what was wrong with is that reduce
function was evaluating the property total as text and concatenated one after the other.
Upvotes: 1
Reputation: 781058
You should just put the total price as a number in the total:
property, not a string. Since you put a string, it's concatenating the strings instead of adding the numbers.
let purchases = []
//function to create shopping cart
function createList() {
let products = ["Winter Hat", "Warm Coat", "Gloves"];
let prices = [27.50, 160.23, 23.99];
let productCode = document.getElementById("productCode").value;
let quantity = document.getElementById("quantity").value;
let message = " Product Code or Quantity invalid. Enter values from list above.";
// message to alert if code is invalid
if (productCode < 1 || productCode > 3 || quantity < 1) {
alert(message);
}
purchases.push({
product: products[productCode - 1],
quantity: quantity,
total: prices[productCode - 1] * quantity
});
// appends list to
let list = document.getElementById("list");
// cals for every item
list.innerHTML = purchases.map(p => {
return "<li>" + p.product + " (Quantity: " + p.quantity + ") Cost: $" + p.total.toFixed(2) + "</li>";
}).join("");
//
document.getElementById("results").innerText = "Total Cost: $" + purchases.reduce((a, c) => {
return a + c.total;
}, 0).toFixed(2);
}
<body>
<h1> Point of Sale System </h1>
<form id="myForm">
This is the point of sale program for a store selling winter clothes.
<ul>
<li>Product Code 1: “Winter Hat” for $27.50</li>
<li>Product Code 2: “Warm Coat” for $160.23</li>
<li>Product Code 3: “Gloves” for $32.99</li>
</ul>
<table>
<tr>
<td>Enter the Product Code:</td>
<!--Input field for productCode-->
<td><input id="productCode" type="number" value=""></td>
</tr>
<tr>
<td>Enter the Quantity:</td>
<!--Input field for quantity-->
<td><input id="quantity" type="number" value=""></td>
</tr>
</table>
<input type="button" value="Add this item to purchase order" onclick="createList()">
<ul id="list"> </ul>
<div id="results"></div>
</form>
</body>
BTW, in general it's simpler to use an array of objects rather than separate arrays for each attribute, e.g.
let products = [
{product: "Winter Hat", price: 27.50},
{product: "Warm Coat", price: 160.23},
{product: "Glovest", price: 23.99}
];
With multiple arrays it's easy for them to get out of sync, but that's almost impossible with an array of objects.
Upvotes: 3