0

I have a table where each row is a separate form:

<tr>
  <form method="post" action="/items/1/edit">
    <td><input type="number" id="duration[1]" onChange="calculateTotal(this);" value="10.0"></td>
    <td><input type="number" id="rate[1]" onChange="calculateTotal(this);" value="25.0"></td>
    <td><input disabled type="number" id="total[1]" value="250.0"></td>
  </form>
</tr>
<tr>
  <form method="post" action="/items/2/edit">
    <td><input type="number" id="duration[2]" onChange="calculateTotal(this);" value="20.0"></td>
    <td><input type="number" id="rate[2]" onChange="calculateTotal(this);" value="50.0"></td>
    <td><input disabled type="number" id="total[2]" value="1000.0"></td>
  </form>
</tr>

I'd like to have the value of the total input be calculated when a change is made to the duration or rate input in the same row.

My "hard coded" function works for the first row only:

function calculateTotal(sender) {

  // use sender.closest('');

  var durationElement = document.getElementById("duration[1]");
  var durationValue = durationElement.value;

  var rateElement = document.getElementById('rate[1]');
  var rateValue = rateElement.value;

  if ( durationValue && rateValue)
  {
    var totalValue = durationValue * rateValue;    
    
    var durationElement = document.getElementById("total[1]");
    durationElement.value = totalValue;
  }
  
}

I think the element.closest() function is the right approach, but I can't get it to work.

How do I adjust it to make it based on the row of the item being edited?

Fiddle

1 Answer 1

1

You can use closest() to get the parent tr element and select all input elements (that are not disabled) inside that element with querySelectorAll and the :not() pseudo-class, then use Array.reduce to sum up the values and assign it to the value property of the input with the disabled attribute:

function calculateTotal(sender) {
  const row = sender.closest('tr');
  const inputs = row.querySelectorAll('input:not([disabled])');
  const sum = [...inputs].reduce((a, b) => a *= +b.value, 1);
  row.querySelector('input[disabled]').value = sum;
}
<table>
  <thead>
    <tr>
      <th>Duration</th>
      <th>Rate</th>
      <th>Total</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <form method="post" action="/items/1/edit">
        <td><input type="number" id="duration[1]" onChange="calculateTotal(this);" value="10.0"></td>
        <td><input type="number" id="rate[1]" onChange="calculateTotal(this);" value="25.0"></td>
        <td><input disabled type="number" id="total[1]" value="250.0"></td>
      </form>
    </tr>
    <tr>
      <form method="post" action="/items/2/edit">
        <td><input type="number" id="duration[2]" onChange="calculateTotal(this);" value="20.0"></td>
        <td><input type="number" id="rate[2]" onChange="calculateTotal(this);" value="50.0"></td>
        <td><input disabled type="number" id="total[2]" value="1000.0"></td>
      </form>
    </tr>
  </tbody>
</table>

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.