sidj sidj - 6 months ago 110
Ruby Question

Rails Jquery compute total from selected checkboxes in a table

So here is my rails view which has a form which pulls the product_items and lets the user check all the items they want to buy and display the total order amount underneath the table. (attached pic)
this is the screenshot of the view

My code looks like below. The server side is good (where I can save the order) but I need some help on the client side js to compute the order total and displaying the order total underneath the table.

<% @cause.product.product_items.each do |item| %>
<td width="60%"><label class="checkbox"><%= f.check_box(:items, { multiple:true, class: 'item_checkbox' },, nil) %><i></i><%= item.title %></label></td>

<label class="select">
<select name="items[<%= %>][qty]">
<option value="0" selected disabled>Qty</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>

<td><b><big><%= number_to_currency(item.price, precision: 0) %></big></b></td>
<% end %>

<label><strong>Total order amount: </strong><span class="lead" id="order_amount"></span></label>

Here is some js, I wanted to identify the checkbox which is checked and grab the qty in that table row (again not sure how to do this)

$(".item_checkbox").change(function() {
if ($(this).is(":checked")) {

alert($(this).siblings($('#select option:selected').text()));


In order to calculate the total amount, you will have to watch for changes for products that get selected/unselected and products quantity that gets changed as well.

You could update your view to look like this (things were left out for the sake of simplicity):

<table id="product-items">
    <% @cause.product.product_items.each do |item|  %>
      <%= tag :tr, data: { price: item.price } do %>
          <label class="checkbox">
           <%= f.check_box(:items, class: 'item_checkbox', %>
           <%= item.title %>
          <label class="select">
          <%= number_to_currency(item.price, precision: 0) %>
      <% end %>
    <% end %>
<div id='total-amount'></div>

As you noticed, I used the tag helper in order to create an HTML5 data attribute with the name price. I did that in order to make it easier to get the product value later on.

Now, since you have your view in place, all you have to do is calculate iterate through the item list every time a product checkbox gets checked/unchecked or a product's quantity changes. You could have something like this:

// This line will add event listeners both to your inputs and selects
// under the #products-items table
$('#product-items input[type=checkbox], #product-items select').change(function(e) {

  // Initialize vars
  var totalAmount = 0;

  // We need only rows that have checked checkboxes
  var $tableRows = $('#product-items tr').has('input[type=checkbox]:checked');

  // Iterate through each row in order get all needed info
  $.each($tableRows, function(i, row) {
    var $row = $(row);

    // Get the quantity for current product
    var quantity = row.find('select').val();

    // You could uncheck the product if quantity is set to 0
    // for better user experience
    if (quantity === 0) {
      $row.find('input').prop('checked', false);
    } else {
      // Get the product price from the data-price attribute
      var price = $'price');

      // I am converting the price to an integer, but you could
      // change that and use parseFloat if you want to
      totalAmount += parseInt(price) * parseInt(quantity);

  $('#total-amount').text('$' + totalAmount);

This way every time you change the quantity or check/uncheck a product, the total amount will be calculated from the beginning.