问题
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)
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.
<tbody>
<% @cause.product.product_items.each do |item| %>
<tr>
<td width="60%"><label class="checkbox"><%= f.check_box(:items, { multiple:true, class: 'item_checkbox' }, item.id, nil) %><i></i><%= item.title %></label></td>
<td>
<label class="select">
<select name="items[<%= item.id %>][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>
</select>
<i></i>
</label>
</td>
<td><b><big><%= number_to_currency(item.price, precision: 0) %></big></b></td>
</tr>
<% end %>
</tbody>
</table>
</div>
<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()));
}
});
回答1:
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">
<tbody>
<% @cause.product.product_items.each do |item| %>
<%= tag :tr, data: { price: item.price } do %>
<td>
<label class="checkbox">
<%= f.check_box(:items, class: 'item_checkbox', item.id) %>
<%= item.title %>
</label>
</td>
<td>
<label class="select">
<select>...</select>
</td>
<td>
<%= number_to_currency(item.price, precision: 0) %>
</td>
<% end %>
<% end %>
</tbody>
</table>
<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 = $row.data('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.
回答2:
Thanks for the help form @ioannis, here is my final answer which solved my problem. This also displays an order summary.
$('#product-items input[type=checkbox], #product-items select').change(function(e) {
// Initialize vars
var totalAmount = 0;
var totalItemAmount = 0;
$('#order_summary').text('');
// We need only rows that have checked checkboxes
$("input:checkbox:not(:checked)")
var $tableRowsNotChecked = $('#product-items tr').has('input[type=checkbox]:not(checked)');
$.each($tableRowsNotChecked, function(i, row) {
var $row1 = $(row);
$row1.find('.item_qty').hide();
});
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) {
// Get the quantity for current product
var $row = $(row);
var qty = $row.find('select').val();
$row.find('.item_qty').show();
// You could uncheck the product if quantity is set to 0
// for better user experience
if (qty === 0) {
$row.find('input').prop('checked', false);
} else {
// Get the product price from the data-price attribute
var price = $row.data("price");
var item = $row.data("item-name");
// I am converting the price to an integer, but you could
// change that and use parseFloat if you want to
totalItemAmount = parseInt(price) * parseInt(qty);
totalAmount += totalItemAmount;
$('#order_summary').append( "<tr><td>" + item + "</td><td>" + qty + "</td><td>$" + parseInt(totalItemAmount) + "</td></tr>");
}
});
$('#order_summary').append( "<tr><td></td><td><strong>Total Amount:</td><td>$" + totalAmount + "</td></strong></tr>");
$('#order-amount').text(totalAmount);
$('#cause_amount').val(totalAmount);
$( "#cause_amount" ).trigger( "change" );
// $('input.submit_contribution').val('Buy Now');
});
来源:https://stackoverflow.com/questions/36704155/rails-jquery-compute-total-from-selected-checkboxes-in-a-table