2

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.

Shantanu
  • 148
  • 3
  • 12
  • `document.getElementById` returns only one item. You should not have more than one HTML element with the same `id`. You should use classes instead, and then use `document.getElementsByClassName`. – Pedro Corso Feb 02 '18 at 12:04
  • Do you need something like this? https://jsfiddle.net/s79my99a/1/ – Kirill Feb 02 '18 at 12:05
  • No this is not what I want. I tried that way as well but it does not seem to working. – Shantanu Feb 02 '18 at 12:14
  • No, it does not work. – Shantanu Feb 02 '18 at 12:27
  • you cannot provide `id` attribute as array or you cannot have multiple elements with same id that is why it only picks the first one try changing the id to unique or add a class and then pick all the elements with that class name – Muhammad Omer Aslam Feb 02 '18 at 14:23
  • Possible duplicate of [jQuery id selector works only for the first element](https://stackoverflow.com/questions/11114622/jquery-id-selector-works-only-for-the-first-element) – Muhammad Omer Aslam Feb 02 '18 at 14:24

3 Answers3

1

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>
Sreekanth Reddy Balne
  • 3,264
  • 1
  • 18
  • 44
0

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.

Francis Leigh
  • 1,870
  • 10
  • 25
  • This does not answer the question. The OP said that the `cost[]` and `qty[]` fields can happen to repeat multiple times. The total must be the sum of all those fields. – Pedro Corso Feb 02 '18 at 12:51
  • Didnt read the Question carefully enough. Have ammended my code. – Francis Leigh Feb 02 '18 at 13:44
0

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="">
Pedro Corso
  • 557
  • 8
  • 22