Reputation: 4231
I'm trying to build a dynamic grid style calculator so users can build up the cost of something, they can add as many rows as needed to capture all the component details. What I need to do now is make my jQuery dynamic too, so it calculates each Total
and Line Total
for each row that's added. As I've got the code at the moment it only works for the first row of the calculator
$(document).ready(function () {
$('.used-amount input[type="text"]')
.on("propertychange, change, keyup, paste, input", function () {
var usedtotal = $(this).val() * $('.used-cost input[type="text"]').val();
$('.used-total').text(usedtotal);
});
$('.used-cost input[type="text"]')
.on("propertychange, change, keyup, paste, input", function () {
var usedtotal = $(this).val() * $('.used-amount input[type="text"]').val();
$('.used-total').text(usedtotal);
});
$('.wastage-cost input[type="text"]')
.on("propertychange, change, keyup, paste, input", function () {
var usedtotal = $(this).val() * $('.wastage-amount input[type="text"]').val();
$('.wastage-total').text(usedtotal);
});
$('.wastage-cost input[type="text"]')
.on("propertychange, change, keyup, paste, input", function () {
var usedtotal = $(this).val() * $('.wastage-amount input[type="text"]').val();
$('.wastage-total').text(usedtotal);
});
$('.calculator input[type="text"]')
.on("propertychange, change, keyup, paste, input", function () {
var linetotal =
($('.used-amount input[type="text"]').val()
* $('.used-cost input[type="text"]').val())
+ ($('.wastage-amount input[type="text"]').val()
* $('.wastage-cost input[type="text"]').val())
$('.line-total').text(linetotal);
});
});
and each row is a razor partial view:
@model TheWorkshop.Web.Models.Edit.CalculatorViewModel
<tr class="calculator-detail">
<td class="component-type">@Html.EnumDropDownListify("ComponentType", @Model.ComponentType)</td>
<td class="component">@Html.DropDownListFor(model => model.SelectedComponentId, Model.ComponentSelectList, "Select...")</td>
<td class="used-amount">@Html.EditorFor(model => model.UsedAmount)</td>
<td class="used-cost">@Html.EditorFor(model => model.UsedCost)</td>
<td class="used-total"></td>
<td class="wastage-amount">@Html.EditorFor(model => model.WastageAmount)</td>
<td class="wastage-cost">@Html.EditorFor(model => model.WastageCost)</td>
<td class="wastage-total"></td>
<td class="line-total"></td>
</tr>
which I'm adding when the button is clicked
$(document).ready(function ($) {
$("button").click(function () {
$.get('@Url.Action("AddCalculatorRow", "Workshop",
new { id = Model.Id } )', function (data) {
$(data).hide().appendTo('.calculator tbody').fadeIn(2000);
});
});
});
and the Controller
public ActionResult AddCalculatorRow()
{
var components = Session.QueryOver<Component>()
.OrderBy(c => c.Name).Asc.List<Component>();
var modelView = new CalculatorViewModel() { Components = components };
return PartialView("_CalculatorRow", modelView);
}
Edit
I've got the Used & Cost total and the Wastage & Cost total working. But can't seem to get LineTotal working and following @JeffB's comments it now looks like this:
$(document)
.on("propertychange, change, keyup, paste, input",
'.calculator input[type="text"]', function () {
var linetotal =
($(this).parent().siblings('.used-amount').find('input').val() *
$(this).parent().siblings('.used-cost').find('input').val())
+ ($(this).parent().siblings('.wastage-amount').find('input').val() *
$(this).parent().siblings('.wastage-cost').find('input').val());
$(this).parent().siblings('.line-total').text(usedtotal);
});
Edit 2
That'll teach me for copy & pasting...
The mistake in my code above is that I've assigned the total of all 4 cells to a linetotal
variable but when updating the line-total
cell have usedtotal
, which is nothing! Changing that to the linetotal variable fixed it and now all cells calculate correctly.
Upvotes: 2
Views: 2240
Reputation: 150148
You are using the non-delegated version of on() that does not bind to UI elements added after the call is made. Try changing
$('.used-amount input[type="text"]')
.on("propertychange, change, keyup, paste, input", function () {
var usedtotal = $(this).val() * $('.used-cost input[type="text"]').val();
$('.used-total').text(usedtotal);
});
to
$(document)
.on("propertychange, change, keyup, paste, input",
'.used-amount input[type="text"]', function () {
var usedtotal = $(this).val() * $('.used-cost input[type="text"]').val();
$('.used-total').text(usedtotal);
});
For more, see the section Direct and delegated events in
Upvotes: 5