How to calculate a totals field in a form with 20 currency input fields?

If you have a form generated by Wappler that has, say, 50 fields and 20 of those are currency input fields that are auto populated depending on selections made by the user, what is the best way to calculate a total and put it in a Totals field ready for inserting into a DB?

I know it is a fairly generic question but was wondering before I build a page.

I assume you want it to be interactive i.e. totals on screen in real time?

Yes that’s right. Live updating when fields are changed.

I guess the most obvious way would be simply define a variable, say varTotal and set it’s value to the sum of the currently fields:

fieldname1.value + fieldname2.value + fieldname2.value etc

1 Like

You mention a variable, so you would avoid trying to do it straight into the totals field itself?

I guess you could do that, using variables if just a habit of mine, find it easier to debug

Yeah that makes sense, more flexible.

If the 20 or so input fields are generated by a repeat from a DB, and therefore I don’t know exactly how many fields there are, how can I do a repeat within a variable so I can add up all the totals on the fly?

image

So I can’t do this

  • fieldname1.value + fieldname2.value + fieldname2.value etc

I really want to do something like

  • variable_name = costs_input_[0].repeat(repeat_value).sum()

which would result in

  • costs_input_1.value + costs_input_2.value + … + costs_input_34.value + costs_input_35.value

Whatever I try is just guesswork and nothing is working. Can you help?

How did you name the inputs? Can you post the repeat region with the input inside code here so we can check it?

Hi @Teodor,

						<div class="form-group row" id="row_specialist" dmx-repeat:repeat1="sc_specialist_q.data.sa_specialist_q">
							<div class="input-group col-sm-6">
								<div class="input-group-prepend">
									<div class="input-group-text">{{specialist_name}}</div>
								</div>
								<div class="btn-group btn-group-toggle d-flex flex-wrap flex-grow-1" is="dmx-repeat" data-toggle="buttons" dmx-bind:repeat="specialist_max+1">
									<label class="btn btn-sm btn-outline-secondary" dmx-bind:for="input_{{specialist_id}}_{{$index}}" dmx-on:click="specialist_total.setValue((specialist_radio.value * specialist_cost).formatNumber(2, &quot;.&quot;, &quot;&quot;))">
										<input class="custom-control-input" 
										type="radio" 
										dmx-bind:id="input_{{specialist_id}}_{{$index}}" 
										dmx-bind:value="$index" 
										id="specialist_radio" 
										name="specialist_radio" 
										value="0">{{$index}}</label>
								</div>
							</div>
							<div class="input-group col-sm-4">
								<div class="input-group-prepend">
									<div class="input-group-text">{{specialist_id}} Cost<i class="fas fa-pound-sign fa-fw fa-lg"></i></div>
								</div>
								<input type="text" class="form-control text-right" dmx-bind:id="inp_costs_input_{{specialist_id}}" dmx-bind:name="costs_input_{{specialist_id}}" placeholder="Cost" id="specialist_total" tabindex="-1" name="specialist_total">
							</div>
						</div>

and results in this compiled html for the 3rd item “Anti Corrosion Protection (additional)”

I am happy to change my approach based on your advice :smile:

So which inputs you want to sum values of? The radio buttons or the text inputs?
If it’s the text inputs, then try something like:

repeat1.items.sum(`specialist_total.value`)

But change the main/outer repeat which you are using to repeat children, otherwise it won’t work.

Screen.mp4 (6.0 MB)

Neil,
remove the repeat region from this row where it is placed now.
id="row_specialist" dmx-repeat:repeat1="sc_specialist_q.data.sa_specialist_q"

Add a repeat children which wraps this row. Then the code i provided will work …
Avoid using just repeat region and use repeat children instead. The repeat children is actually a repeat component in App Connect, the normal repeat is a dynamic attribute. Only component can have properties, data and events - that’s why the calculation code which i provided won’t work with the regular repeat.

1 Like

Superb!
Works a treat.
I wish I could learn quickly and retain this wonderful knowledge.

1 Like

Hi @Teodor, one final question on this subject, how can I easily use the selected checkbox ID in the text at the end, I can’t seem to get that to work either :frowning_face:

Morning @Teodor, any ideas on this last question?

Should it be ‘pushed’ with SetValue when the ‘3’ is clicked or can it be ‘fetched’ by setting some sort of listener? Either way I can’t seem to get the ‘value’ of ‘3’ into an input field or variable.

Well how do you calculate the amount in the text field? What’s the formula?

Once I did something similar by using a cookie.

In answer to your question
dmx-on:click=“specialist_total.setValue((specialist_radio.value * specialist_cost).formatNumber(2, “.”, “”))”

But I think I’m asking the wrong question, sorry.

The following is what I am after (I have hidden the Specialist options that were talked about above).

I am sure this makes sense but I cannot get the various fields to calculate.
The ‘Paint & sundries’ at £88 should be added to the ‘Parts’ at £77. I have done this with

  • dmx-bind:value="(inp_costs_paint.value + inp_costs_parts.value)"

But it concatenates the figures (‘8877’) rather than adding them together (‘165’).

Then the user should press either ‘VAT’ or ‘Repairer is not VAT registered’ which would then show the VAT figure in the input field next to it.

I thought this might work but doesn’t

  • dmx-on:click="((vat_yes_no.value == 138 ? 0.2 : 0) * costs_cont_rep.value).formatNumber(2, “.”, “”)"

(where 138 is the value of the ‘VAT’ field)

and then finally in the ‘Grand total’ field it adds the 165 to the 33 to give 198.00

All very straight forward I am sure but I can’t seem to get it to work.

That’s because the inputs always return strings. So the string 88 added to the string 77 equals 8877.
You need to convert them to number first, using the toNumber() formatting option.

dmx-bind:value="(inp_costs_paint.value.toNumber() + inp_costs_parts.value.toNumber())"
1 Like