2

I have multiple Numeric textbox as shown below in the snippet, all are currency format textbox's. How can I sum the values of textboxes in Class Name Charges and display the total sub-total-Of-Charges textbox and subtract if any value in textbox's with class=sub from sub-total-Of-Charges textbox value.

I have used the following jQuery Code which is working but two problems.

  1. Doesn't Keep the currency format

  2. the value of net-invoiced-amount is updated only when I update textbox value in textbox class .sub same thing .sub-total-Of-Charges value is updated on .Charges are updated but I need to re-calculate or update the value net-invoiced-amount or .sub-total-Of-Charges whenever .sub or .charges textbox's values are changed.

    $(document).ready(function () {
     $(document).on("change", ".charges", function () {
         var calculated_total_sum = 0;
    
         $(".charges").each(function () {
             var get_textbox_value = $(this).val();
             if ($.isNumeric(get_textbox_value)) {
                 calculated_total_sum += parseFloat(get_textbox_value);
             }
         });
         $(".sub-total-Of-Charges").val(calculated_total_sum);
     });
    

    $(document).on("change", ".sub", function () {

         var netInvoicedAmount = $(".sub-total-Of-Charges").val();
    
         $(".sub").each(function () {
             var get_textbox_value = $(this).val();
             if ($.isNumeric(get_textbox_value)) {
                 netInvoicedAmount -= parseFloat(get_textbox_value);
             }
         });
         $(".net-invoiced-amount").val(netInvoicedAmount).trigger("change");
     });
    

    });

kuka muk
  • 349
  • 2
  • 18

2 Answers2

1

As you've used jQuery for your project, I'm also writing this answer using the library.

$(document).ready(function() {
  let $references = {
    subtotal: $('#SubtotalOfCharges').first(),
    net: $('#NetInvoicedAmount').first(),
    fields: {
      subtract: $('input.sub'),
      charge: $('input.charges')
    }
  }
  
  function calculateSum($elements) {
    return Array.from($elements).reduce((previousValue, element) => {
      val = $(element).val();
      
      if(val)
        previousValue += parseFloat($(element).val());
      
      return previousValue;
    }, 0)
  }
  
  $(document).on('change', 'input', function() {
    let sum = {
      subtract: calculateSum($references.fields.subtract),
      charge: calculateSum($references.fields.charge),
    }
    
    $references.subtotal.val(sum.charge);
    $references.net.val(sum.charge - sum.subtract);
  });
})
input,
label {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<label>Total Direct Labor Charge</label>
<input id="TotalDirectLaborCharges" class="charges">

<label>TotalIndirectLaborCharges</label>
<input id="TotalIndirectLaborCharges" class="charges">

<label>TotalContractCharges</label>
<input id="TotalContractCharges" class="charges">

<label>TotalTravelCharges</label>
<input id="TotalTravelCharges" class="charges">

<label>TotalAdjustments</label>
<input id="TotalAdjustments" class="sub">

<label>CostsAlreadyPaid</label>
<input id="CostsAlreadyPaid" class="sub">

<label>Other</label>
<input id="Other" class="sub">

<label>SubtotalOfCharges</label>
<input id="SubtotalOfCharges" readonly class="sub-total-Of-Charges">

<label>NetInvoicedAmount</label>
<input id="NetInvoicedAmount" readonly class="net-invoiced-amount">

How does it work?

  1. Instead of manually triggering a change event whenever a .sub (or .charges) is changed, to calculate the subtotal/net amount, you can bind the event handler to both of the input groups and run the calculations once.
  2. I've used $references to tidy up the code a little bit and a reduce function is used to calculate the sum of a field group.
  3. Array.from is used to create a native Javascript array from the jQuery object.

For more information on Array.reduce, visit its documentation here, and for more information on Array.from visit here.

Finally, a feasible solution is to use input prefixes. Every UI framework normally has one built-in, otherwise, you can take a look at Bootstrap's input groups here (Especially, .input-group-prepend).

Farsad
  • 501
  • 5
  • 14
  • Hi @Farsad Thank you, on your demo it works exactly how I wanted but I cant get it to work on my end, may be it because I use kendo numeric textbox?. – kuka muk Oct 31 '20 at 05:36
  • It might be due to that as well as other factors like whether your browser supports `Array.from` and `Array.reduce` or you might need a polyfill to use them. Anyhow, are there any errors in your console? – Farsad Oct 31 '20 at 05:47
  • no error at all in the console thats the first thing I checked – kuka muk Oct 31 '20 at 05:51
  • May you add `console.log` after `let sum = {....}` (logging sum, and $references)? – Farsad Oct 31 '20 at 05:53
  • 1
    Hi, nice answer :) – Swati Oct 31 '20 at 06:20
1

You need to get reference of textbox where you need to set the updated value using data("kendoNumericTextBox") and then set new value using .value("newwvalue") this will update new value according to the format which you have set earlier .

Also , use $(this).attr("aria-valuenow") to get the original value of textbox without any currency and change your selector to $(".k-formatted-value.charges") to get only input value from particular textbox .Currently , when you will inspect html generated it has 2 input box with same class that's the reason total sum is not working.

Demo Code :

$("#TotalDirectLaborCharges, #TotalIndirectLaborCharges, #TotalContractCharges, #TotalTravelCharges, #TotalAdjustments, #TotalAdjustments, #CostsAlreadyPaid, #Other, #NetInvoicedAmount ,#SubtotalOfCharges").kendoNumericTextBox({
  decimals: 2,
  format: "c"
});

//add both selector
$(document).on("change", ".charges,.sub", function() {

  var calculated_total_sum = 0;
  $(".k-formatted-value.charges").each(function() {
    //get original value without currecny
    var get_textbox_value = $(this).attr("aria-valuenow");
    if ($.isNumeric(get_textbox_value)) {
      calculated_total_sum += parseFloat(get_textbox_value);
    }
  });
  //get kendo textbox
  var numerictextbox = $("#SubtotalOfCharges").data("kendoNumericTextBox");
  //set value
  numerictextbox.value(calculated_total_sum);


});
//add both selector
$(document).on("change", ".sub ,.charges", function() {
  //get value from inputbox
  var netInvoicedAmount = $("#SubtotalOfCharges").data("kendoNumericTextBox").value();
  $(".k-formatted-value.sub").each(function() {
    //get original value
    var get_textbox_value = $(this).attr("aria-valuenow");
    if ($.isNumeric(get_textbox_value)) {
      netInvoicedAmount -= parseFloat(get_textbox_value);
    }
  });
  //set value in invoice amt
  var numerictextbox = $("#NetInvoicedAmount").data("kendoNumericTextBox");
  numerictextbox.value(netInvoicedAmount);

});
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2020.3.1021/styles/kendo.common.min.css">

<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2020.3.1021/styles/kendo.rtl.min.css">

<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2020.3.1021/styles/kendo.default.min.css">

<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2020.3.1021/styles/kendo.mobile.all.min.css">



<script src="https://code.jquery.com/jquery-1.12.3.min.js"></script>

<script src="https://kendo.cdn.telerik.com/2020.3.1021/js/angular.min.js"></script>

<script src="https://kendo.cdn.telerik.com/2020.3.1021/js/jszip.min.js"></script>

<script src="https://kendo.cdn.telerik.com/2020.3.1021/js/kendo.all.min.js"></script>

<div class="quarter m-l-lg m-y text-right">

  <label class="m-r-lg required" asp-for="TotalDirectLaborCharges">Total Direct Labor Charge<br /></label>
  <input id="TotalDirectLaborCharges" class="charges" /><br />
  <label class="m-r-lg required" asp-for="TotalIndirectLaborCharges">TotalIndirectLaborCharges<br /></label><br />

  <input id="TotalIndirectLaborCharges" class="charges" /><br />
  <label class="m-r-lg required" asp-for="TotalContractCharges">TotalContractCharges</label><br />

  <input id="TotalContractCharges" class="charges" /><br />

  <label class="m-r-lg required" asp-for="TotalTravelCharges">TotalTravelCharges</label><br />

  <input id="TotalTravelCharges" class="charges" /><br />
  <label class="m-r-lg required" asp-for="TotalAdjustments">TotalAdjustments</label><br />

  <input id="TotalAdjustments" class="sub" /><br />

  <label class="m-r-lg required" asp-for="CostsAlreadyPaid">CostsAlreadyPaid</label><br />

  <input id="CostsAlreadyPaid" class="sub" /><br />
  <label class="m-r-lg required" asp-for="Other">Other</label><br />

  <input id="Other" class="sub" /><br />
  <label class="m-r-lg required" asp-for="SubtotalOfCharges">SubtotalOfCharges</label><br />

  <input id="SubtotalOfCharges" readonly class="sub-total-Of-Charges" />

  <br />

  <label class="m-r-lg required" asp-for="Other">NetInvoicedAmount</label><br />

  <input id="NetInvoicedAmount" readonly class="netInvoicedAmount" />

</div>
Swati
  • 28,069
  • 4
  • 21
  • 41
  • Hi @Swati Thank you! only one thing Net Invoiced Amount doesn't change when i update Charges, NetInvoice Amount changes only when .sub are changed :) – kuka muk Oct 31 '20 at 05:31
  • 1
    Ahh :P i didn't saw that ..wait i will update that as well – Swati Oct 31 '20 at 05:37
  • Hi , check updated code i have just added both selector `sub` and `charges` to both events .Also , you can merge them together . – Swati Oct 31 '20 at 06:09