Javascript Calculate Sum of Repeater Fields

itpates 11 Oct, 2018
I have a repeater form where check names, and check amounts are entered, with the ability to add or remove check entries.

I can get this information via PHP easy enough and that works fine for emailing results. But attempting to calculate a sum of the checks via JavaScript prior to submitting is proving elusive. I need it to dynamically update the sum as new entries are typed, and if an entry is deleted. Are there any examples at all? Here is a segment of the generated code for the check amount:

I'm not a Javascript guru - PHP is more my strong suite. But JQuery does not seem to like the generated fields. However, I've yet to figure out how to code an onkeyup function that captures the value and sends a sum to another static field.
<input class="checkadd" onblur="if (this.value=='') this.value='0.00';" onfocus="if (this.value=='0.00') this.value='';" onkeyup="return calculateSum()" data-events="[]" placeholder="Amount" id="amount0" value="" name="checklista[0][checkamount]" type="text">

<input class="checkadd" onblur="if (this.value=='') this.value='0.00';" onfocus="if (this.value=='0.00') this.value='';" onkeyup="return calculateSum()" data-events="[]" placeholder="Amount" id="amount1" value="" name="checklista[1][checkamount]" type="text">

<input class="checkadd" onblur="if (this.value=='') this.value='0.00';" onfocus="if (this.value=='0.00') this.value='';" onkeyup="return calculateSum()" data-events="[]" placeholder="Amount" id="amount2" value="" name="checklista[2][checkamount]" type="text">

<input id="totalSum" type="text" class="form-control" name="totalSum">
healyhatman 12 Oct, 2018
Answer
Well what have you called your fields? If you've called them (for example) field_{var:area_repeater#} just need to do something like
var total = 0; 
jQuery('input[name^="field_"]').each(function() {
total += parseInt($(this).val());
});
jQuery('input[name="total_field"]').val(total);
Or something along those lines.

Or EVEN BETTER - create a hidden field called "calc". In the repeater field, under event, add an onchange ->add to and put "calc" in the element identifier field. You can then use the calculator widget to show the value.
itpates 12 Oct, 2018
Thanks! I didn't know I could use the ^. I may need to tweak things though. The check name and amount both start with checklista - one is checklista[row][checkname] and the other is checklista[row][checkamount] - which keeps the check even with its associated amount in the list. I could do it consecutively with unique names but if a field gets left empty on accident that shifts the whole column and puts things where they do not belong. I think trying to parse a multidimentional array in Javascript was what was seriously screwing with my noodle.

itpates 12 Oct, 2018
The main problem I've had with using the Event "Add to" property is, if the amount is changed, it just adds to the total as if it was a new entry. If the item was removed using the remove button, it also does not affect the total, so new items after that just add to it as if the previous item had not been removed. So, I've pretty much given up the idea of using that. Perhaps the next version of Chronoforms will have that ironed out. So...pretty much stuck wrangling Javascript.🙂
itpates 12 Oct, 2018
The scenario is, on closing, the manager is entering the list of checks and the amount of each check. A running total on the bottom of the form needs to update as checks are entered. And as is common to humans, mistakes are made. A number typed in wrong. So the manager will go retype that number. Or perhaps a check is entered twice, so a check will be removed. The running total needs to reflect these changes accurately.
itpates 12 Oct, 2018
I guess I could use different names for the check name and check amount, and force an entry into one or the other is nothing is typed - such as 0.00 in the amount field, and "Name" in the name field, just in case these are overlooked. All to ensure that the checks match up with their corresponding amounts when I parse it with PHP for the emailed form.
itpates 12 Oct, 2018
This is returning an NaN for some reason:
function calculateSum() {
var sum = 0;
jQuery('input[name^="checklist"]').each(function() {
sum += parseFloat($(this).val());
});
jQuery('input[name="totalSum"]').val(sum);
}

jQuery('.checkadd').on('keyup', function() {
calculateSum();
});
itpates 12 Oct, 2018
Ah - my test was picking up NULL from the fields that were not filled out. Will insert "0" values for those until a number is entered in.
itpates 12 Oct, 2018
This is working on my static example. It totally bombs on the Repeater, however. The first field populates the totalSum input. But every other field added after that, nada. I even tried moving the calculateSum() to an onKeyUp in attributes - onkeyup:return calculateSum(); or - and it still failed.onkeyup:calculateSum();

What's weird, if I have stuff typed into the new fields, and go back to the original field and type new numbers, it calculates the input from the generated input fields. But if keyup events in the generated input fields are simply not working at all.
function calculateSum() {
var sum = 0;
jQuery('input[class^="checkadd"]').each(function() {
if (!isNaN(this.value) && this.value.length != 0) {
sum += parseFloat($(this).val());
}
});
jQuery('input[name="totalSum"]').val(sum);
}

jQuery('.checkadd').on('keyup', function() {
calculateSum();

});
itpates 12 Oct, 2018
Created a new thread for the new problem. Thanks for your help, healyhatman.🙂
GreyHead 12 Oct, 2018
Hi itpates ,

I suspect that the problem may be that the code isn't being attached to the inputs that are newly created by the repeater. There is a FAQ for CFv5 where I did something similar - iirc I linked my code to the Add and Remove buttons and then had it attach the On KeyUp event to all the current inputs.

Bob
itpates 12 Oct, 2018
This worked. Now I'm trying to get the Remove button to run the calculateSum() function too. No luck so far.
function calculateSum() {
var sum = 0;
jQuery('input[class^="checkadd"]').each(function() {
if (!isNaN(this.value) && this.value.length != 0) {
sum += parseFloat($(this).val());
}
});
jQuery('input[name="totalSum"]').val(sum);
}

jQuery(document).on('keyup', 'input[class^="checkadd"]', function() {
calculateSum();
});
itpates 12 Oct, 2018
I tried this and added recalc to the list of classes the button has, but I think the "click" event is already bound to another function:
jQuery(document).on('click', '[class="recalc"]', function() {
calculateSum();
});
healyhatman 12 Oct, 2018
You can bind as many click events as you want to an element and they'll all run one after the other
itpates 15 Oct, 2018
I was thinking since .remove told Javascript to delete that element, then anything after that would end up being disregarded. I need to figure out a way to capture the value of that field first, then delete that from the total if that field is removed. Or a way to run the calc function whenever any change is made - either from keyup in the field itself, or adding/removing fields.
This topic is locked and no more replies can be posted.

VPS & Email Hosting 20% discount
hostinger