Gary Kukat
Gary Kukat

Reputation: 79

Function Using map() and push() Displaying Incorrect Output

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

enter image description here

Correct/Desired Output

enter image description here

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

Answers (3)

Gopinath
Gopinath

Reputation: 4937

The problem is due to 2 issues:

  1. typo : presence of + in front of the word "Gloves"

  2. 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:

  1. Remove the typo (+ character) from products array definition

  2. 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>

Output enter image description here

Upvotes: 0

Mike Rs.
Mike Rs.

Reputation: 17

I've made few changes that I would like for you to evaluate:

  1. 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
    });
    
  2. 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

Barmar
Barmar

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

Related Questions