1

I have mockup like this

The HTML table to work with

The table above will calculate subtotal and total_harga using the entered value in jumlah. Calculations work fine, but my code is still using static JavaScript.

If there are a lot of rows in the table, it will be troublesome, if you have to write the getElementById code for all the inputs. How to use looping so that all the inputs can be handled without describing the table rows one by one. This is my HTML and JavaScript.

<div class="container">
<table class="tg" id="sales">
    <thead>
    <tr>
        <th class="tg-0lax">No.</th>
        <th class="tg-0lax">Item</th>
        <th class="tg-0lax">Jumlah</th>
        <th class="tg-0lax">Harga Satuan</th>
        <th class="tg-0lax">Diskon Satuan</th>
        <th class="tg-0lax">Sub-Total</th>
    </tr>
    </thead>
    <tbody>
    <tr>
        <td class="tg-0lax">1</td>
        <td class="tg-0lax">MIE INSTAN</td>
        <td class="tg-keyup"> <input type="text" id="input1" name="fname" onkeyup="CalculationPrice()" placeholder="Masukan jumlah"><br></td>
        <td class="tg-0lax" id="harga_satuan1">5000</td>
        <td class="tg-0lax" id="diskon_satuan1">500</td>
        <td class="tg-0lax" id="sub_total1"></td>
    </tr>
    <tr>
        <td class="tg-0lax">2</td>
        <td class="tg-0lax">SUSU UHT</td>
        <td class="tg-keyup"><input type="text" id="input2" name="fname" onkeyup="CalculationPrice()" placeholder="Masukan jumlah"><br></td>
        <td class="tg-0lax" id="harga_satuan2">6000</td>
        <td class="tg-0lax" id="diskon_satuan2">1000</td>
        <td class="tg-0lax" id="sub_total2"></td>
    </tr>
    <tr>
        <td class="tg-0lax">3</td>
        <td class="tg-0lax">KERIPIK</td>
        <td class="tg-keyup"> <input type="text" id="input3" name="fname" onkeyup="CalculationPrice()" placeholder="Masukan jumlah"><br></td>
        <td class="tg-0lax" id="harga_satuan3">8000</td>
        <td class="tg-0lax" id="diskon_satuan3">500</td>
        <td class="tg-0lax" id="sub_total3"></td>
    </tr>
    <tr>
        <td class="tg-0lax"></td>
        <td class="tg-1lax" colspan="4">TOTAL HARGA</td>
        <td class="tg-0lax" id="total_price"></td>
    </tr>
    </tbody>
</table>

this is my code javascript :

function CalculationPrice() {

    let input1 = document.getElementById("input1").value;
    let input2 = document.getElementById("input2").value;
    let input3 = document.getElementById("input3").value;
  
    let hargaSatuan1 = document.getElementById("harga_satuan1").innerText;
    let hargaSatuan2 = document.getElementById("harga_satuan2").innerText;
    let hargaSatuan3 = document.getElementById("harga_satuan3").innerText;
  
    let diskonSatuan1 = document.getElementById("diskon_satuan1").innerText;
    let diskonSatuan2 = document.getElementById("diskon_satuan2").innerText;
    let diskonSatuan3 = document.getElementById("diskon_satuan3").innerText;
  
 

     if(input1.length == 0){
        let total1 = document.getElementById("sub_total1").innerHTML = 0;
      }else if(input1.length > 0){
          let subinput =  (parseInt(hargaSatuan1) - parseInt(diskonSatuan1)) * parseInt(input1)
          let total1 = document.getElementById("sub_total1").innerHTML = subinput;
      } 
      
      if(input2.length == 0){
          let total2 = document.getElementById("sub_total2").innerHTML = 0;
      }
      
      else if(input2.length > 0){
        let subinput2 = (parseInt(hargaSatuan2) - parseInt(diskonSatuan2)) * parseInt(input2) 
        let total2 = document.getElementById("sub_total2").innerHTML = subinput2;
      }
      
      if(input3.length == 0){
          let total3 = document.getElementById("sub_total3").innerHTML = 0;
      }
      
      else if(input3 !== null){
        let subinput3 = (parseInt(hargaSatuan3) - parseInt(diskonSatuan3)) * parseInt(input3)
        let total3 = document.getElementById("sub_total3").innerHTML = subinput3;
      }
      
      let total1 = document.getElementById("sub_total1").innerText
      let total2 = document.getElementById("sub_total2").innerText
      let total3 = document.getElementById("sub_total3").innerText
      
      
      let total_price = parseInt(total1) + parseInt(total2) + parseInt(total3)
      let totalPriceHtml =  document.getElementById("total_price").innerHTML = formatRupiah(total_price, "Rp.");
      
      }
    
      
      function formatRupiah(angka, prefix) {
        let number_string = angka.toString().replace(/[^,\d]/g, ""),
          split = number_string.split(","),
          sisa = split[0].length % 3,
          rupiah = split[0].substr(0, sisa),
          ribuan = split[0].substr(sisa).match(/\d{3}/gi);
      
        if (ribuan) {
          separator = sisa ? "." : "";
          rupiah += separator + ribuan.join(".");
        }
      
        rupiah = split[1] != undefined ? rupiah + "," + split[1] : rupiah;
        return prefix == undefined ? rupiah : rupiah ? "Rp. " + rupiah : "";
      }
Teemu
  • 21,017
  • 6
  • 49
  • 91
Marka
  • 15
  • 4
  • Is the table created dynamically on the back-end? If it is, you should also fill the `subtotal`s and `total` on the server for the first table to show. – Teemu May 18 '21 at 06:53
  • no, data is statis , but i want to improve my code using loop – Marka May 18 '21 at 07:20

2 Answers2

2

Using ids on a table makes a lot of unnecessary work, it's much easier to rely on the structure of a static table. And, instead of inline event handlers, we can benefit from event delegation. Here's an example of how to listen input event on tbody and a simple reduce loop to calculate the total sum of subtotals.

const tbody = document.querySelector('#sales'),
  rows = Array.from(tbody.rows), // All the rows of the tbody
  total = rows.pop().cells[2]; // The TOTAL HARGA cell

function calcTot(e) {
  const value = +e.target.value || 0,
    rowIndex = e.target.closest('tr').rowIndex - 1, // Constant 1 = the amount of the rows in thead
    cells = Array.from(rows[rowIndex].cells),
    harga = +cells[3].textContent,
    diskon = +cells[4].textContent,
    sub = cells[5];

  sub.textContent = harga - diskon * value;
  total.textContent = rows.reduce((acc, row) => {
    return acc += +row.cells[5].textContent;
  }, 0);
}

// Calculate the first sums
rows.forEach(row => {
  // Call calcTot with a fake event object
    calcTot({target: row.cells[2]});
});

tbody.addEventListener('input', calcTot);
<div class="container">
  <table class="tg">
    <thead>
      <tr>
        <th class="tg-0lax">No.</th>
        <th class="tg-0lax">Item</th>
        <th class="tg-0lax">Jumlah</th>
        <th class="tg-0lax">Harga Satuan</th>
        <th class="tg-0lax">Diskon Satuan</th>
        <th class="tg-0lax">Sub-Total</th>
      </tr>
    </thead>
    <tbody id="sales">
      <tr>
        <td class="tg-0lax">1</td>
        <td class="tg-0lax">MIE INSTAN</td>
        <td class="tg-keyup"> <input type="text" name="fname[]" placeholder="Masukan jumlah"></td>
        <td class="tg-0lax">5000</td>
        <td class="tg-0lax">500</td>
        <td class="tg-0lax"></td>
      </tr>
      <tr>
        <td class="tg-0lax">2</td>
        <td class="tg-0lax">SUSU UHT</td>
        <td class="tg-keyup"><input type="text" name="fname[]" placeholder="Masukan jumlah"></td>
        <td class="tg-0lax">6000</td>
        <td class="tg-0lax">1000</td>
        <td class="tg-0lax"></td>
      </tr>
      <tr>
        <td class="tg-0lax">3</td>
        <td class="tg-0lax">KERIPIK</td>
        <td class="tg-keyup"> <input type="text" name="fname[]" placeholder="Masukan jumlah"></td>
        <td class="tg-0lax">8000</td>
        <td class="tg-0lax">500</td>
        <td class="tg-0lax"></td>
      </tr>
      <tr>
        <td class="tg-0lax"></td>
        <td class="tg-1lax" colspan="4">TOTAL HARGA</td>
        <td class="tg-0lax"></td>
      </tr>
    </tbody>
  </table>
</div>

Notice also, that I've moved the sales id from the table tag to the tbody tag, and how the event handler function is used to calculate the subtotal and total sums without an actual event by passing an object which contains the needed information of the event object.

Teemu
  • 21,017
  • 6
  • 49
  • 91
  • SUbtotal is harga satuan - diskon satuan * jumlah, – Marka May 18 '21 at 07:54
  • but total_harga is NaN – Marka May 18 '21 at 07:59
  • @BimoAnugrah I've fixed the math according to your comment. I can't reproduce the `NaN` issue, make sure you've the unary plus operators everywhere they occurs in my code, and the table structure (cell count) is the same. Did you also move the `id` from `table` to `tbody`? – Teemu May 18 '21 at 08:04
  • total_harga still Nan – Marka May 18 '21 at 08:10
  • 1
    THANKS a lot ! works perfectly , i just change in this code sub.textContent = harga - diskon * value, TO sub.textContent = (harga - diskon )* value; – Marka May 18 '21 at 08:16
1

First, you should have the data source (in an array of objects). Such as:

var dataSource = [
    { id: 1, item: "MIE INSTAN", HargaSatuan: 5000, DiskonSatuan: 500 },
    { id: 2, item: "SUSU UHT", HargaSatuan: 6000, DiskonSatuan: 1000 },
    { id: 3, item: "KERIPIK", HargaSatuan: 8000, DiskonSatuan: 500 },
]

Then, you can loop through this array to construct your table, using either JQuery or JavaScript's "insertRow()".

Reference link for JavaScript's insertRow()

<html>

<head>
  <style>
    table {
      border-collapse: collapse;
    }
    table, td, th {
      border: 1px solid black
    } 
  </style>
</head>

<body>

  <table id="myTable">
    <tr>
      <th class="tg-0lax">No.</th>
      <th class="tg-0lax">Item</th>
      <th class="tg-0lax">Jumlah</th>
      <th class="tg-0lax">Harga Satuan</th>
      <th class="tg-0lax">Diskon Satuan</th>
      <th class="tg-0lax">Sub-Total</th>
    </tr>
  </table>
  <br>


  <script>
    function myFunction() {

      var dataSource = [{
          id: 1,
          item: "MIE INSTAN",
          hargaSatuan: 5000,
          diskonSatuan: 500
        },
        {
          id: 2,
          item: "SUSU UHT",
          hargaSatuan: 6000,
          diskonSatuan: 1000
        },
        {
          id: 3,
          item: "KERIPIK",
          hargaSatuan: 8000,
          diskonSatuan: 500
        },
      ]


      var table = document.getElementById("myTable");
      dataSource.forEach(function(data, index) {
        var row = table.insertRow(index + 1);
        var noCell = row.insertCell(0);
        var itemCell = row.insertCell(1);
        var jumlahCell = row.insertCell(2);
        var hargaSatuanCell = row.insertCell(3);
        var diskonSatuanCell = row.insertCell(4);
        var subTotalCell = row.insertCell(5);

        noCell.innerHTML = data.id;
        itemCell.innerHTML = data.item;
        hargaSatuanCell.innerHTML = data.hargaSatuan;
        diskonSatuanCell.innerHTML = data.diskonSatuan

      })

    }
    myFunction()
  </script>

</body>

</html>

You only need to modify the datasource and refresh the table if there are any new data.

This might not be the best method of doing this, but this will give you a basic understanding on the algorithm and steps required for your needs.

HanKeat
  • 86
  • 3