What is the best way to choose the checked items and calculate the total price by adding up all the prices of the selected items?

Seeking help with utilizing JavaScript to identify and collect all checked items from an HTML file.
I'm looking to determine which items have been selected from a menu, each of which has an associated price.
How can I access the prices of the checked items in a JavaScript array?
My goal is to calculate the total price of all checked items from the HTML menu.
Making progress on the code. Using a forEach() loop to iterate through the checked items and isolate them by their id.
Considered using split('Checkbox') but unsure how to make it work to sum up the prices from the menuItem array and get the total: total += menu.price.

var menuItems = 
  [ { itemName: 'salad',        price: 13.95 } 
  , { itemName: 'pancakes',     price:  8.95 } 
  , { itemName: 'omlette',      price:  8.95 } 
  , { itemName: 'croissant',    price:  5.95 } 
  , { itemName: 'muffin',       price:  8.95 } 
... (content continues)
      <input type="checkbox" id="milCheckbox" name="milk" />
      $3.95
    </td>
  </tr>
</table>
<div>
  <form>
    <input type="submit" value="Submit" id="sub">
    <input type="reset" value="Reset">
  </form>
</div>  
<div style="margin-top: 10px;">
  <button type="button">Total Amount</button>
</div>
        
<script type="text/javascript" src="/js/menu.js"></script>
</body>
</html>

Answer №1

To create a similar setup, you can set the price for each item using a data attribute in the checkbox input. Just be cautious of any potential floating-point errors.

document.getElementById("SubmitButton").addEventListener('click', function(e) {
  e.preventDefault();
  var selectedItems = document.querySelectorAll('.item-selection:checked');
  
  var selectedItemPrices = [];
  var total = 0;
  
  for (var i = 0; i < selectedItems.length; i++) {
    var price = Number.parseFloat(selectedItems[i].getAttribute('data-price'));
  
    selectedItemPrices.push({
      itemName: selectedItems[i].getAttribute('name'),
      price: price.toFixed(2)
    });
    
    total += price;
  }
  
  console.log(selectedItemPrices);
  console.log(total.toFixed(2));
});
<table style="width:100%">
  <tr>
    <th>BreakFast</th>
    <th>Lunch</th>
    <th>Beverages</th>
  </tr>
  <tr>
    <td><label for="Pancakes"><b>Blueberry Pancakes</b></label>
      <input class="item-selection" type="checkbox" id="panCheckbox" name="pancakes" data-price="8.95" />$8.95</td>
    <td><label for="burger"><b>Cheeseburger</b></label>
      <input class="item-selection" type="checkbox" id="burg" name="burger" data-price="10.95"/>$10.95</td>
    <td><label for="Coffee"><b>Black Coffee:</b></label>
      <input class="item-selection" type="checkbox" id="cofCheckbox" name="coffee" data-price="1.95"/>$1.95</td>
  </tr>
  <tr>
    <td><label for="Omelette"><b>Vegetable Omelette</b></label>
      <input class="item-selection" type="checkbox" id="omlCheckbox" name="omlette" data-price="8.95"/>$8.95</td>
    <td><label for="Wrap"><b>Teriyaki Wrap:</b></label>
      <input class="item-selection" type="checkbox" id="rapCheckbox" name="wrap" data-price="12.95"/>$12.95</td>
    <td><label for="Tea"><b>Green Tea:</b></label>
      <input class="item-selection" type="checkbox" id="teCheckbox" name="tea" data-price="11.95"/>$11.95</td>
  </tr>
  <tr>
    <td> <label for="Croissant"><b>Croissant:</b></label>
      <input class="item-selection" type="checkbox" id="crosCheckbox" name="croissant" data-price="5.95"/>$5.95</td>
    <td><label for="salad"><b>Ceasar Salad:</b></label>
      <input class="item-selection" type="checkbox" id="salCheckbox" name="sald" data-price="13.95"/>$13.95</td>
    <td><label for="beer"><b>Corona Beer 12 oz:</b></label>
      <input class="item-selection" type="checkbox" id="BerCheckbox" name="Beer" data-price="5.95"/>$5.95</td>
  </tr>
  <tr>
    <td> <label for="Muffin"><b>Blueberry Muffin</b></label>
      <input class="item-selection" type="checkbox" id="MufCheckbox" name="muffin" data-price="8.95"/>$8.95</td>
    <td><label for="soup"><b>Tomato Soup:</b></label>
      <input class="item-selection" type="checkbox" id="souCheckbox" name="soup" data-price="11.95"/>$11.95</td>
    <td><label for="Milk"><b>Chocolate Milk:</b></label>
      <input class="item-selection" type="checkbox" id="milCheckbox" name="milk" data-price="3.95"/>$3.95</td>
  </tr>
</table>
<div>
  <form>
    <input id="SubmitButton" type="submit" value="Submit" id="sub">
    <input type="reset" value="Reset">
  </form>
</div>
<div style="margin-top: 10px;">
  <button type="button">Total Amount</button>
</div>

Answer №2

Give this a try! The solution provided will function based on checking/unchecking the checkbox. If you require it to work on a button click instead, just let me know and I can make the necessary modifications.

I've made adjustments to your HTML code as well. You now have the option of using the value attribute of the checkbox to assign specific item values, which can then be utilized for further calculations in JavaScript. Feel free to reach out if you encounter any issues!

<!DOCTYPE html>
<html xmlns:th="http://thymeleaf.org">
<head>
    <title>MENU</title>
    <script type="text/javascript" src="/js/menu.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script type="text/javascript">

        var total = 0;
        $(document).ready(function () {
            $('input[type="checkbox"]').change(function () {
                var ischecked = $(this).is(':checked');
                if (!ischecked) {
                    total -= parseFloat($(this).val());
                } else {
                    total += parseFloat($(this).val());
                }
                console.log(total.toFixed(2));
            });
        });

    </script>
    <link rel="stylesheet" type="text/css" href="css/menu.css">
</head>
<body>
    <form>
        <div class="name">
            <h1>JOE'S FAMILY DINER</h1>
        </div>

        <table style="width:100%">
            <tr>
                <th>BreakFast</th>
                <th>Lunch</th>
                <th>Beverages</th>
            </tr>
            <tr>
                <td>
                    <label for="Pancakes"> <b>Blueberry Pancakes</b> </label>
                    <input type="checkbox" id="panCheckbox" name="pancakes" value="8.95" />$8.95

                </td>
                <td>
                    <label for="burger"> <b>Cheeseburger</b> </label>
                    <input type="checkbox" id="burg" name="burger" value="10.95" />
                    $10.95
                </td>
                <td>
                    <label for="Coffee"> <b>Black Coffee:</b> </label>
                    <input type="checkbox" id="cofCheckbox" name="coffee" value="1.95" />
                    $1.95
                </td>
            </tr>
             [...]
        	<div>
            	<input type="submit" value="Submit" id="sub">
            	<input type="reset" value="Reset">
        	</div>
        	<div style="margin-top: 10px;">
            	<button type="button">Total Amount</button>
       		</div>
    	</form>
	</body>
</html>

Answer №3

Using FormData, you can easily retrieve only the checked elements in a form.

This method requires reorganizing your HTML to suit this functionality.

Here's a practical example of how to utilize forms effectively:

const menuItems = 
  { BreakFast :
    [ { itemName: 'pancakes',  price: 8.95, label: 'Blueberry Pancakes' }
    , { itemName: 'omlette',   price: 8.95, label: 'Vegetable Omelette' }
    , { itemName: 'croissant', price: 5.95, label: 'Croissant'          }
    , { itemName: 'muffin',    price: 8.95, label: 'Blueberry Muffin'   }
    ]
  , Lunch :
    [ { itemName: 'cheeseburger', price: 10.95, label: 'Cheeseburger'  }
    , { itemName: 'teriyaki',     price: 12.95, label: 'Teriyaki Wrap' }
    , { itemName: 'salad',        price: 13.95, label: 'Ceasar Salad'  }
    , { itemName: 'soup',         price: 11.95, label: 'Tomato Soup'   }
    ]
  , Beverages :
    [ { itemName: 'coffee', price:  1.95, label: 'Black Coffee'      }
    , { itemName: 'tea',    price: 11.95, label: 'Green Tea'         }
    , { itemName: 'beer',   price:  5.95, label: 'Corona Beer 12 oz' }
    , { itemName: 'milk',   price:  3.95, label: 'Chocolate Milk'    }
    ]
  }

const
  myForm = document.querySelector('#my-form-id')
, total  = document.querySelector('#total > em')

for (let menu in menuItems) // build the menu
  {
  let menuPart = document.createElement('fieldset') 
  menuPart.innerHTML = `<legend>${menu}</legend>`
  menuItems[menu].forEach(item=>
    {
    menuPart.innerHTML += `
        <label>
          <b>${item.label}</b>
          <input type="checkbox" name="${item.itemName}" value="${item.price}">
          <em>$ ${item.price}</em>
        </label>`
    })
  myForm.querySelector('.cols-3-parts').appendChild(menuPart)
  }
myForm.onsubmit = e =>
  {
  e.preventDefault() // disable submit while testing

  let inputJSON = Array.from(new FormData(myForm))
    .reduce((r,[name,value])=>{ r[name]= isNaN(value) ? value : Number(value); return r} ,{}) 
  console.log( JSON.stringify( inputJSON ))
  setTimeout(console.clear, 2000);
  }
myForm.onreset = e =>
  {
  total.textContent = '0.00'
  }
myForm.oninput = e =>
  {
  let  totalVal = 0;
  Array.from(new FormData(myForm))
    .forEach(([name,value])=> totalVal += isNaN(value) ? 0 : Number(value) ) 
    
  total.textContent = totalVal.toFixed(2)
  }
form#my-form-id {
  width   : 60em;
  padding : .4em;
  }
button {
  margin : 1em .4em 0 0;
  width  : 6em;
  }
.cols-3-parts {
  display   : flex;
  flex-wrap : wrap;
  }
.cols-3-parts fieldset {
  flex-grow : 1;
  width     : 30%;
  }
.cols-3-parts fieldset label {
  display : block;
  float   : left;
  clear   : left; 
  }
.cols-3-parts fieldset label b {
  display       : inline-block;
  width         : 11.4em;
  text-overflow : "";
  white-space   : nowrap;
  overflow      : hidden;
  }
.cols-3-parts fieldset label b::after {
  content     : '...............................';
  color       : grey;
  font-weight : normal;
  }
.cols-3-parts fieldset label input[type="checkbox"] {
  vertical-align: top;
  }
.cols-3-parts fieldset label em {
  font-size      : .8em;
  vertical-align : top;
  }
<h1>JOE'S FAMILY DINER</h1>

<form action="xx" id="my-form-id">
  <div class='cols-3-parts'> </div>

  <button type="submit">Submit</button>
  <button type="reset" >Reset</button>
</form>

<p id="total">
  Total : $ <em>0.00</em>
</p>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to cycle through a nested JS object?

I am currently utilizing useState and axios to make an API call, retrieve the response, and pass it to a Component for rendering. const [state,setState] = useState([]); const getCurrData = () => { axios.get('working api endpoint url').then(r ...

Javascript: Accessing a shared variable within the class

Embarking on my JavaScript programming journey filled me with optimism, but today I encountered a challenge that has left me stumped. Within my tutorial project, there exists a class named Model which contains both private and public variables. Of particu ...

Unable to modify the background image of a div using jQuery

I'm encountering an issue in my script where I tried to implement an event that changes the background-image of a div when a button is clicked, but it's not functioning as intended. Below is the code snippet: HTML <div class="col-md-2 image ...

Learning about the functions Promise.all and Array.map()

My current project involves retrieving data from multiple APIs and aggregating them into a final array that will be displayed in the UI using React. Let me explain the scenario. First, I retrieve the main data from the primary API: const response = await ...

Create static HTML web pages using information from a text file

Exploring a new concept of a random joke generator that loads a unique html page with a quirky joke every time. Currently, the main index page is structured like this: <!DOCTYPE html> <html> <head><title>Jokes</title> ...

Issue with retrieving the current location while the map is being dragged

How can I retrieve the current latitude and longitude coordinates when the map is dragged? I've tried using the following code: google.maps.event.addListener(map, 'drag', function(event) { addMarker(event.latLng.lat(), event.la ...

Steps for inserting a video into a new div upon selecting a hyperlink

Looking for a way to link menu elements to corresponding videos in adjacent divs? I have two divs set up - one with the menu list and another right next to it where the videos should be loaded. Forms seem like a potential solution, but I lack expertise i ...

How can I troubleshoot the unresponsive remove div function on my website?

My code is running fine on CodePen (link provided below), but for some reason, it's not working properly in the web browser. I am executing the code from localhost and the button isn't responding as expected. CODE Here is my Visual Studio code ...

What methods are available for implementing hover effects within attributes using a JavaScript object?

const customPanelStyle = { 'background-color': 'red', 'border': '1px solid green', ':hover'{ 'background': 'blue' } } class some extends React.Component{ rende ...

Tips for invoking a function using ng-model together with the ng-model value

Within a div element, I have a text field where I am using ng-model to capture the value. I need to trigger a function for validation when a date is entered in the text field. How can I achieve this while still utilizing ng-model? Any suggestions on how to ...

Remove the most recent file in a MongoDB collection using a DELETE request

As I delve into the world of REST APIs, one task on my to-do list is to delete the last POST in my mongoDB collection using a DELETE route with mongoose. Despite searching for answers, none seem to provide guidance on achieving this deletion through a rout ...

What is the best way to ensure that posts made with Contentlayer stay dynamic for future posts on Vercel?

My issue is that on the webpage I have set up using contentlayer, I display my blog posts from GitHub through Vercel. However, when I publish a new post on GitHub, I am unable to see it because it has not been built yet. What can I do on the Nextjs13 site ...

Repetitive bouncing in a trampoline leads to the error message "Call stack has reached maximum size"

I have been delving into the world of blockchain and experimenting with a simple implementation of "proof of work". Proof of work: export function mineBlock(difficulty: number, block) { const prefix = Array(difficulty + 1).join("0"); function mine(b ...

An issue arose when trying to display React components within an Angular application

Attempting to incorporate React components into an Angular 7 application has been a challenge for me. While I have successfully rendered simple React components, I encountered the following error message (displayed in the browser console) when attempting t ...

Designate a Cookie for individual users

Currently, I am in the process of building a straightforward Wordpress website that aims to monitor a user's order using a specific Cookie. Although most of the functionalities are already implemented, an unexpected issue has surfaced. Upon logging i ...

Having issues with passing data to a Modal on eventClick using FullCalendar with ReactJS, receiving a "cannot read property of undefined" error. Any advice on how

My MERN stack application utilizes the FullCalendar plugin, even though I am aware that mixing jQuery with React is not ideal. Unfortunately, I am a novice developer and running behind schedule. The goal is to allow users to click on an event on the calen ...

Encountering Issues with NextJS Dynamic SSR: Mobile Devices stuck on loading screen

Issue: The dynamic import feature of Next JS is encountering loading issues specifically on mobile browsers such as Google Chrome and Safari on IOS. Strangely, the functionality works smoothly on desktop browsers like Google Chrome and Mozilla. The projec ...

Using Vuejs to dynamically render a select dropdown based on the initial selection made in the first dropdown menu

I am facing an issue with two drop-down menus. The second menu's choices need to be filtered and displayed based on the selection made in the first drop-down. The RoomID value from the first drop-down is used to filter an array of objects for the seco ...

Firefox experiencing issues with the onchange event

Here in this block of code, I have two dropdown lists: one for department and the other for section name. Based on the selected department, I dynamically change the options available for the section name dropdown list and then populate the values from both ...

Vuejs unstyled content flash

I encountered an issue while loading a page with Vue. Initially, I am able to access variables like @{{ value }} but once the page is fully loaded, the variable becomes invisible. How can I resolve this issue? I have already included Bootstrap and all scri ...