Form: run function when any field changes?

I have a Mortgage Calculator form that has the Financed Amount, Interest Rate, and Term Length.

I want to prepopulate it with default values, and when ones of the values changes, update the monthly payment amount.

As I have it now, it will only run the function when Submit is clicked. How do I set it to run when any of the fields are changed?

<html>
	
<form action="">
  <label>APR%: <input type="text" value="4" id="apr" name="APR"/></label>
  <label>Loan Term: <input type="text" value="30" id="trm" name="APR"/></label>
  <label>Loan Amount: <input type="text" value="450000" id="amt" name="amt"/></lablel>
  <input  type="text" id="pmt" name="mPmt"/>
  <input type="button" id="sbt" value="Submit" />
  <input type="reset" id="rst" value="Reset Form" />
</form>
</html>
<script>
var term;
var apr;
var amt;
var mPmt;


window.onload = function()
{
  document.getElementById("apr").focus();
  document.getElementById("sbt").onclick = getValues;

};

//use toFixed(2) to set the precision of the mPayment. Use it on an int.
function getValues()
{
  term = document.getElementById("trm").value;
  apr = document.getElementById("apr").value;
  amt = document.getElementById("amt").value;
  apr /= 1200;
  term *= 12;
  mPmt = calculatePayment();
  document.getElementById("pmt").value = "$" + mPmt.toFixed(2);
};

function calculatePayment()
{
	var payment = amt*(apr * Math.pow((1 + apr), term))/(Math.pow((1 + apr), term) - 1);
	return payment;
}

</script>

You can use the change or/and keyup event listeners.

HTML

<form id='calculator'>
  <label for='apr'>APR%: 
    <input type="number" value="4" id="apr" name="APR"/>
  </label>
  <label for='trm'>Loan Term: 
    <input type="number" value="30" id="trm" name="APR"/>
  </label>
  <label for='amt'>Loan Amount: 
    <input type="number" value="450000" id="amt" name="amt" step='100'/>
  </label>
  <input type="text" id="pmt" name="mPmt" readonly/>
  <input type="button" id="sbt" value="Submit" />
  <input type="reset" id="rst" value="Reset Form" />
</form>

JS

function getValues() {
  const term = Number(document.querySelector("#trm").value);
  const apr = Number(document.querySelector("#apr").value);
  const amt = Number(document.querySelector("#amt").value);
  const pmt = document.querySelector("#pmt")
  
  mPmt = calculatePayment(term * 12, apr / 1200, amt);
  
  // a temporary fix e.g. for APR of 0% or an empty loan term
  if (!isNaN(mPmt) && isFinite(mPmt)) {
    pmt.value = '$' + mPmt.toFixed(2);
  } else {
    pmt.value = ''
  }
}

function calculatePayment(term, apr, amt) {
	const payment = amt * (apr * Math.pow((1 + apr), term))/(Math.pow((1 + apr), term) - 1);
	return payment;
}

window.addEventListener('DOMContentLoaded', () => {

  const calculator = document.querySelector('#calculator');
  
  // listen for keyup and change events
  ['keyup', 'change'].forEach((type) => {
    // add the listeners to the form
    calculator.addEventListener(type, (event) => {
      // check if the event was fired from an input number box
      if (event.target.matches('input[type="number"]')) {
        getValues();
      }
    })
  })
  
  document.querySelector("#apr").focus();
})

Note I have added a temporary fix for the result being $NaN (Not a number) or $Infinity. This occurs when the APR is 0% or say the loan term is just an empty box. It probably needs a better fix, but I am limited for time.

1 Like

Hi @jeremy58, instead of listening to click events of the submit button, you might listen to input events of the entire form:

HTML

<form id="my-form">
  ...
</form>

JS

const form = getElementById('my-form')
form.addEventListener('input', getValues)

(x-post)

1 Like

How about something like the following?

  var term;
  var apr;
  var amt;
  var mPmt;

  window.onload = function() {
    // Call getValues() when the page loads to prepopulate the monthly payment amount
    getValues();

    // Add event listeners to each input element to update the monthly payment amount when the values change
    document.getElementById("apr").addEventListener("change", getValues);
    document.getElementById("trm").addEventListener("change", getValues);
    document.getElementById("amt").addEventListener("change", getValues);
  };

  function getValues() {
    term = document.getElementById("trm").value;
    apr = document.getElementById("apr").value;
    amt = document.getElementById("amt").value;
    apr /= 1200;
    term *= 12;
    mPmt = calculatePayment();
    document.getElementById("pmt").value = "$" + mPmt.toFixed(2);
  };

  function calculatePayment() {
    var payment = amt*(apr * Math.pow((1 + apr), term))/(Math.pow((1 + apr), term) - 1);
    return payment;
  }