Shantanu
Shantanu

Reputation: 148

Calculate values of multiple fields and display for every row in Javascript

I have an invoice which is not a table but inside a div in html are some input fields. These fields are being created dynamically by clicking on a button.

<li><input type="text" id="cost[]" name="unit[]" value="<?php echo $val->unit ; ?>"> </li>
<li><input type="text" id="qty[]" name="rate[]" value="<?php echo $val->rate ; ?>"> </li>
<li><input type="text" id="price[]" name="total[]" value="<?php echo $val->total ; ?>"> </li>

Now I want to multiply unit with rate and display it in the total field.

My Javascript is

 window.onkeyup=function() {

        var str = document.getElementById("cost[]").value;
        var str1 = document.getElementById("qty[]").value;
        var price = parseFloat(str*str1);
        document.getElementById("price[]").value = price;
}

The javascript above works fine but it works only for the first row. For the rest of the rows below the first row, it does not work. I want the calculation for all the rows. I have seen some of the answers but none of them works in my case.

Any help is welcome.

Upvotes: 2

Views: 2937

Answers (3)

Francis Leigh
Francis Leigh

Reputation: 1960

var invoices = document.querySelectorAll('.invoice')
var handleChange = function (foo, bar, total) {
	let str = +foo.value || 0
	let str2 = +bar.value || 0

  total.value = parseFloat(str*str2)
}

invoices.forEach(function(invoice) {
	
  var foo = invoice.querySelector('input[name=foo]')
  var bar = invoice.querySelector('input[name=bar]')
  var total = invoice.querySelector('input[name=total]')
  
  foo.addEventListener('keyup', function() {
  	handleChange(foo, bar, total)
  })
  bar.addEventListener('keyup', function() {
  	handleChange(foo, bar, total)
  })
})
<div class="invoice">
  <input type="text" name="foo">
  <input type="text" name="bar">
  <input type="text" name="total">
</div>
<div class="invoice">
  <input type="text" name="foo" value="">
  <input type="text" name="bar" value="">
  <input type="text" name="total">
</div>
<div class="invoice">
  <input type="text" name="foo">
  <input type="text" name="bar">
  <input type="text" name="total">
</div>
<div class="invoice">
  <input type="text" name="foo">
  <input type="text" name="bar">
  <input type="text" name="total">
</div>
<div class="invoice">
  <input type="text" name="foo">
  <input type="text" name="bar">
  <input type="text" name="total">
</div>

Notice how i prepended a + to the parse of str & str2 this operator turns any String number into a Number I recommend you do this because when querying the value of a input[type=text] - it will give you the value represented as a String...

This is fine when multiplying e.g '1'*'2'// = 2...

But, if you want to ADD two numbers together, your sum will be interpreted as concatenation e.g '2'+'2' // = '22'

It may also be smart to default your values to 0 if a value is not provided or a Alphabetic or special character is put into the input e.g 'hello'*'2' // = NaN

try

var str = +foo.value || 0;

var str1 = +bar.value || 0;

var price = parseFloat(str*str1);

Alternatively, make your input type="number" this will limit the user to only be able to input numbers.

Upvotes: 0

Sreekanth Reddy Balne
Sreekanth Reddy Balne

Reputation: 3424

What I observe from your code is that you might be using same ids for multiple items.

The "id" attribute assigns a name to an element. This name must be unique in a document.

Though we have a workaround like:

document.querySelectorAll("[id='someID']");

to select all elements with same "id"s, your HTML will be invalid.

And this is why we have "class" instead. A class is a group of elements.

Though I have used "name" attribute.

May be what you are looking for:

 window.onkeyup=function() {
	
var items = document.querySelectorAll(".item");
var itemsArray = Array.prototype.slice.call(items,0);
var unit, rate, total, net = 0;
itemsArray.forEach(function(el){
	unit = el.querySelector('input[name="unit[]"]').value;
	rate = el.querySelector('input[name="rate[]"]').value;
	total = unit * rate;
	el.querySelector('input[name="total[]"]').value = total;
	net+=total;
});
document.getElementById('net').value=net;
}
<div class='item'>
	<li><input type="text"  name="unit[]" value=""> </li>
	<li><input type="text"  name="rate[]" value=""> </li>
	<li><input type="text" name="total[]" value=""> </li>
</div>

<br><br>

<div class='item'>
	<li><input type="text" name="unit[]" value=""> </li>
	<li><input type="text" name="rate[]" value=""> </li>
	<li><input type="text" name="total[]" value=""> </li>
</div>

</br></br>

<li><input id='net' type="text" name="net[]" value=""> </li>

Upvotes: 1

Pedro Corso
Pedro Corso

Reputation: 557

As I've stated before, It's not recommended to keep multiple elements with the same id on your HTML. But if you want to keep things that way, then you can make use of document.querySelectorAll and iterate over the elements to sum their value and store it in the total:

window.onkeyup=function() {

  var costs = document.querySelectorAll("input[id='cost[]'");
  var qtys = document.querySelectorAll("input[id='qty[]'");
  
  var price = 0;
  
  for (var i = 0; i < costs.length; i++){
   price += +costs[i].value + +qtys[i].value;
  }

  document.getElementById("price[]").value = price;
}
<input type="text" id="cost[]" name="unit[]" value="2">
<input type="text" id="qty[]" name="rate[]" value="4">
<br>
<input type="text" id="cost[]" name="unit[]" value="2">
<input type="text" id="qty[]" name="rate[]" value="4">
<br>
<input type="text" id="cost[]" name="unit[]" value="2">
<input type="text" id="qty[]" name="rate[]" value="4">
<br>
<input type="text" id="cost[]" name="unit[]" value="2">
<input type="text" id="qty[]" name="rate[]" value="4">

<input type="text" id="price[]" name="total[]" value="">

Upvotes: 0

Related Questions