Simon Martin
Simon Martin

Reputation: 4231

jquery total and subtotal for each dynamic row is only calculating first row

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

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

Answers (1)

Eric J.
Eric J.

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

http://api.jquery.com/on/

Upvotes: 5

Related Questions