Summing Table Line Values

Asked

Viewed 69 times

0

Good morning, you guys!

I have a table that is populated with the data of an XML, and each row of the table has quantity, unit value, ipi and total input. Then I would like that when editing an information in the line the system calculates the Total Product ref. the altered line. Follow the table below to better understand, I need to use javascript for this.

<table width="100%">
    <tr>
        <th>Produto</th>
        <th>Quantidade</th>
        <th>Valor Unit.</th>
        <th>IPI</th>
        <th>Total Produto</th>
    </tr>
    <tr>
        <td>Telha Cimento</td>
        <td><input type="txt" id="quantidade" name="quantidade" value="10"></td>
        <td><input type="txt" id="valor-unit" name="valor-unit" value="150,00"></td>
        <td><input type="txt" id="valor-ipi" name="valor-ipi" value="85,90"></td>
        <td><input type="txt" id="valor-total" name="valor-total" value="2.359,00"></td>
    </tr>
    <tr>
        <td>Bloco de Vidro</td>
        <td><input type="txt" id="quantidade" name="quantidade" value="5"></td>
        <td><input type="txt" id="valor-unit" name="valor-unit" value="55,00"></td>
        <td><input type="txt" id="valor-ipi" name="valor-ipi" value="10,90"></td>
        <td><input type="txt" id="valor-total" name="valor-total" value="329,50"></td>
    </tr>
</table>

2 answers

2

Don’t need and jQuery for that. Basically:

  • listen to the event input in each tr
  • extracts the elements
  • takes account of the fact that , in Javascript should be .
  • formats the total with the locale

Note: you cannot have repeated Ids on the same page. These Ids of each input must be removed...

const trs = document.querySelectorAll('tr');
trs.forEach(tr => {
  tr.addEventListener('input', () => {
    const [quantidade, valorUnit, valorIpi, valorTotal] = tr.querySelectorAll('input');
    const total = Number(quantidade.value) * Number(valorUnit.value.replace(/,/, '.'));
    valorTotal.value = total.toLocaleString();
  });
});
<table width="100%">
  <tr>
    <th>Produto</th>
    <th>Quantidade</th>
    <th>Valor Unit.</th>
    <th>IPI</th>
    <th>Total Produto</th>
  </tr>
  <tr>
    <td>Telha Cimento</td>
    <td><input type="txt" id="quantidade" name="quantidade" value="10"></td>
    <td><input type="txt" id="valor-unit" name="valor-unit" value="150,00"></td>
    <td><input type="txt" id="valor-ipi" name="valor-ipi" value="85,90"></td>
    <td><input type="txt" id="valor-total" name="valor-total" value="2.359,00"></td>
  </tr>
  <tr>
    <td>Bloco de Vidro</td>
    <td><input type="txt" id="quantidade" name="quantidade" value="5"></td>
    <td><input type="txt" id="valor-unit" name="valor-unit" value="55,00"></td>
    <td><input type="txt" id="valor-ipi" name="valor-ipi" value="10,90"></td>
    <td><input type="txt" id="valor-total" name="valor-total" value="329,50"></td>
  </tr>
</table>

  • I didn’t really know what to do with valueUnit, valueIpi... so I omitted the value in the account. But this is simple to fix.

  • Can I suggest not generating new arrays from the return of the method querySelectorAll? There is no reason why, in this case, the return of querySelectorAll is already an object that has the iterator method (Symbol.iterator), and also its own method forEach.

  • @user140828 truth, old habits, corrected.

1

An option using jQuery and formatting the result with two decimal places is using in the calculation result:

.toLocaleString("pt-BR", { style: "decimal", minimumFractionDigits: "2"})

Create an event listener input for each input field and search for input values on the whole line by the attribute name (Remove the repeated id’s, because they are not necessary).

As Javascript calculates decimal points separated by a point, it is necessary to first remove the dots separating thousands and then replace the comma separating decimals by dots:

.replace(/\./g, '').replace(',', '.')

Then multiply the value of the quantity by the value of the product and add with the IPI. See what I put || 0 in the values to avoid NaN if a field of some value is empty, assuming the value 0 if it is empty.

Note also that I used parseFloat only the value of the IPI, since it is the only value that will be added, otherwise the value would be concatenated. The others who will be multiplied need no conversion.

When calculating the fields, play the result to the last field with name='valor-total'.

Will stay like this:

$(function(){
   
   $("td input").on("input", function(){
      
      var linha = $(this).closest("tr");
      var quantidade = $("[name='quantidade']", linha).val();
      var unidade = $("[name='valor-unit']", linha).val().replace(/\./g, '').replace(',', '.') || 0;
      var ipi = parseFloat($("[name='valor-ipi']", linha).val().replace(/\./g, '').replace(',', '.')) || 0;
      var calc = quantidade*unidade+ipi;
      $("[name='valor-total']", linha).val(calc.toLocaleString("pt-BR", { style: "decimal", minimumFractionDigits: "2"}));
   });
   
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table width="100%">
    <tr>
        <th>Produto</th>
        <th>Quantidade</th>
        <th>Valor Unit.</th>
        <th>IPI</th>
        <th>Total Produto</th>
    </tr>
    <tr>
        <td>Telha Cimento</td>
        <td><input type="txt" name="quantidade" value="10"></td>
        <td><input type="txt" name="valor-unit" value="150,00"></td>
        <td><input type="txt" name="valor-ipi" value="85,90"></td>
        <td><input type="txt" name="valor-total" value="2.359,00"></td>
    </tr>
    <tr>
        <td>Bloco de Vidro</td>
        <td><input type="txt" name="quantidade" value="5"></td>
        <td><input type="txt" name="valor-unit" value="55,00"></td>
        <td><input type="txt" name="valor-ipi" value="10,90"></td>
        <td><input type="txt" name="valor-total" value="329,50"></td>
    </tr>
</table>

Browser other questions tagged

You are not signed in. Login or sign up in order to post.