0

I'd like to count the sum of all the numeric values of a lot of input fields inside a form, every time one of the values changes. I think this code is quite closer, but when I change twice the same input it is wrong.

tot = 0;
$('form#form-id :input').change(function(){
  $("form#form-id :input").each(function(){
    tot += Number($(this).val());
  });
  console.log(tot);
});

This also seems to works well on jsFiddle https://jsfiddle.net/yq9zenaz/ but I get NaN on production.

2
  • Define the variable locally... Commented Jun 23, 2016 at 14:00
  • 1
    Maybe you could check the value before adding to make sure it's a number? if(!isNaN($(this).val())) { //Your code } Commented Jun 23, 2016 at 14:01

6 Answers 6

2

Define the variable locally or else global value will be updated every time change handler is invoked.

$('form#lines-form-1 :input').change(function() {
  var tot = 0;
  $("form#lines-form-1 :input").each(function() {
    tot += Number($(this).val());
    // Could be written as
    // tot += +this.value;
  });
  $('#tot-qty').text(tot);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<form id="lines-form-1">
  <input type="number" name="i1">
  <br>
  <input type="number" name="i2">
  <br>
  <input type="number" name="i3">
  <br>
  <input type="number" name="i4">
  <br>
  <input type="number" name="i5">
  <br>

</form>
<div id="tot-qty">0</div>

Updated Fiddle

Sign up to request clarification or add additional context in comments.

3 Comments

But in this case, you can't access tot globally. I don't know if needed, but you cant. Just set tot = 0; every time change got tiggered, and you'll be fine.
Very precise, thanks. Andwhat if I have some default values on it? jsfiddle.net/yq9zenaz/6
jsfiddle.net/rayon_1990/yq9zenaz/7 Invoke .change() initially...
1

Reset tot inside the callback, otherwise you will be continue adding numbers, but it's not the correct value.

Updated your fiddle: https://jsfiddle.net/yq9zenaz/1/

var tot = 0;
$('form#lines-form-1 :input').change(function(){
    tot = 0;
    $("form#lines-form-1 :input").each(function(){
        tot += Number($(this).val());
    });
    console.log(tot);
    $('#tot-qty').text(tot);
});

If you don't need tot to be accessible globally, just use it on the inside only:

$('form#lines-form-1 :input').change(function(){
    var tot = 0;
    $("form#lines-form-1 :input").each(function(){
        tot += Number($(this).val());
    });
    console.log(tot);
    $('#tot-qty').text(tot);
});

Comments

1

You need to reset tot to zero each time

tot = 0;
$('input').change(function(){
  tot = 0;
  $("input").each(function(){
    tot += Number($(this).val());
  });
  console.log(tot);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input/>
<input/>

Comments

1

You should initialise variable tot within change handler.

$('form#lines-form-1 :input').change(function(){
  tot = 0;
  $("form#lines-form-1 :input").each(function(){
    tot += Number($(this).val());
  });
  console.log(tot);
  $('#tot-qty').text(tot);
}); 

Comments

1

Declare tot variable inside change and declare it with variable keyword

$('form#lines-form-1 :input').change(function(){
var tot = 0;
  $("form#lines-form-1 :input").each(function(){
    tot += Number($(this).val());
  });
  console.log(tot);
  $('#tot-qty').text(tot);
});

JSFIDDLE

Comments

1

Here's an alternate solution:

What we do is get the jQuery collection of all inputs, use .map() to create a jQuery collection of input values, use .get to get the array from the jQuery object. After all of that we run .reduce with an add function on the array to get the sum of all values.

var $inputs = $("form#lines-form-1 :input");

$inputs.change(function() {
  var tot = $inputs
    .map(function() {
      return Number(this.value);
    })
    .get()
    .reduce(function(a, b) {
      return a + b;
    });

  console.log(tot);
  $('#tot-qty').text(tot);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="lines-form-1">
<input type="number" name="i1"><br>
<input type="number" name="i2"><br>
<input type="number" name="i3"><br>
<input type="number" name="i4"><br>
<input type="number" name="i5"><br>

</form>
<div id="tot-qty">0</div>

And if you want tot to be in the parent scope, you can move it's declaration to outside the .change event and it'll still work since it's being completely reassigned instead of added to.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.