Home > Net >  JQuery - Instant calculation/conversion in a dynamic table
JQuery - Instant calculation/conversion in a dynamic table

Time:12-21

I do have a dynamic HTML table (rows can be added) and I 'simply' want to read the value in Liter and convert it to USG while the user is entering the values (take value in Liters, convert it and put it in the USG input field).

Dynamic HTML Table

I already created a function which gets executed after each insert of Liter values:

_onFuelLiterInput(event) {

            
            // For all inputFields with name = fuelLiter

            $('#tankdaten .'   DEFINES.class.DYNAMIC_TABLE).find('tbody tr input.fuelLiter').each((index, element) => {

                let $element = $(element);
                let $ind = $(index);
                
                let value = 0;
                let USG = 0;

                // Read Value in Liters
                try {
                    value = parseFloat($element.val());
                } catch (e) {
                    value = 0;
                }

                // ignore empty values
                if (isNaN(value)) {
                    value=0;
                }
                
                // Convert Liter to USG 
                USG = Math.round(value * 0.26417205235815 * 100)/100;
                // Update field with USG value
                $(event.target).closest('tr').find('.fuelUSG').val(USG);

            });

The HTML contains a for each row as in the following example:

<td >
    <input  type="text" name="Fuel[<?php echo $i; ?>][fuelLiter]"
        data-name="fuelLiter"
        value="<?php echo $row['fuelLiter']; ?>" />
</td>
<td >
    <input  type="text" name="Fuel[<?php echo $i; ?>][fuelUSG]"
        data-name="fuelUSG"
        value="<?php echo $row['fuelUSG']; ?>" />
</td>

As the field name is the same in every row I'm struggling to reference the field in the same and the $(event.target).closest('tr').find('.fuelUSG').val(USG); does not solve it as it loses the same lign.

Any idea how to do it?

I already tried $(event.target).closest('tr').find('.fuelUSG').val(USG); and was hoping the same with name 'fuelUSG' is going to be updated. But it unfortunately doesn't work.

CodePudding user response:

I must confess I don't remember if I touched something that was the key to make it work...(surely I correctly added the event handler that you were missing)

Anyway in this demo, apart the very first function that just adds rows using a template, it factors the logic for the conversion in two step so that:

  • the lowest layer just takes care of getting the string value as argument and returns the conversion as number
  • the the upper layer that takes as argument the specific input element itself; grabs its value still as string; passes it to the conversion function described before and sets its sibling input with the value converted

the whole game is set up on a single loop over all the input.UsedFuel that for each of them on every row just performs the conversion with the values already set at the beginning and adds the keyup event listener that will perform the conversion in real time to the row the user is editing.

//adds a number of rows to the main table (for the sake of the demo)
function addRows(n, random = true){  
  const max = 1000;
  for(let i=1;i<=n;i  ){
    const row = $('#tableRow')[0].content.cloneNode(true);
    if(random){
      const rndFuel = Math.floor(Math.random() * max);
      $(row).find('.UsedFuel').val(rndFuel);
    }
    $('.table tbody').append(row);
  }  
}
//adds 10 rows
addRows(5, false); //5 with the default value = 100
addRows(5, true); //5 with random values max 1000

//-------------------------

//initialize the page.. given the table in #tankdaten .table
$('#tankdaten .table')
  //finds all the input.UsedFuel in tbody rows
  .find('tbody tr input.UsedFuel')
    //and for each one of them
    .each((index, element) => {
      //performs the conversion for the initial value (set with the value attribute)
      performConversion(element);
      //adds the keyup event handler to the element, that..
      $(element).on('keyup',(event)=>{        
        //will perform the conversion to the element triggering the event
        performConversion( $(event.target) );
      });
    });

//starting from the litersInputElement passed,
//it performs the conversion and sets the value of the sibling .fuelUSG
function performConversion(litersInputElement){
  const USG = convertLitersToUSG($(litersInputElement).val());
  $(litersInputElement).closest('tr').find('.fuelUSG').val(USG);
}

//given the amount of liters (as string) returns the USG as number
function convertLitersToUSG(liters) {
  let parsed = parseFloat(liters);
  if (isNaN(parsed))
    parsed = 0;

  return Math.round(parsed * 0.26417205235815 * 100)/100;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="tankdaten">
  <table >
    <tbody>
    </tbody>
  </table>
</div>

<template id="tableRow">
  <tr>
    <td >
      <input
        
        type="text"                       
        value="100" />
    </td>
    <td >
      <input
        
        type="text"                      
        value="" />
    </td>
  </tr>
</template>

  • Related