'Why only the first function inside onclick event handler sets innertext properly and the second one gives NaN?

I tried to create a basic expense tracker website using DOM manipulation. When I am calling two function at a time in an onClick event handler, the one I called at first place does it's job fine to set the innertext in html. But the function I call after first one sets the innerText as NaN! It behaves same even if I replace the position of the function. Here is my HTML & JS code in order.

function expenseCalculation() {

  expenseAndBalance("expense");
  expenseAndBalance("balance");

}

// expense calculation shared function
function calculationReuse(inputId) {
  const expneseInput = document.getElementById(inputId);
  const expneseInputValue = expneseInput.value;
  const expenseAmount = parseFloat(expneseInputValue);
  expneseInput.value = "";
  return expenseAmount;
}
// Getting Total expenses & balance Text
function expenseAndBalance(textId) {
  const income = calculationReuse("income-input");
  const foodExpense = calculationReuse("food-input");
  const rentExpnese = calculationReuse("rent-input");
  const clothesExpense = calculationReuse("clothes-input");
  const totalExpense = foodExpense + rentExpnese + clothesExpense;
  const balance = income - totalExpense;
  const moneyAmount = document.getElementById(textId);
  const moneyAmountText = moneyAmount.innerText;
  const moneyAmountNumber = parseFloat(moneyAmountText);
  if (textId == "expense") {
    moneyAmount.innerText = totalExpense;
  } else {
    moneyAmount.innerText = balance;
  }
}
<header>
  <h1 class="text-3xl font-semibold text-emerald-500 text-center mt-12 heading">
    Expense Tracker 💴
  </h1>
</header>
<main>
  <!-- Image part -->
  <div class="grid grid-cols-2 gap-4 mt-12 mx-8 media-query">
    <div class="money-pic">
      <img src="images/coins-paper-money-globe-white-statistic-form-background.jpg" alt="" />
    </div>
    <!-- Calculation part -->
    <div class="calculation-part bg-slate-200">
      <div class="texts-and-inputs mx-auto">
        <h3 class="text-center font-semibold text-lg my-4">Income</h3>

        <div class="calculation-inputs text-center">
          <h2 class="inline text-base font-medium">Income:</h2>
          <input class="bg-neutral-300" type="text" name="" id="income-input" />
          <h3 class="text-center font-semibold text-lg my-4">Expenses</h3>
          <div class="block mb-2">
            <h2 class="inline text-base font-medium">Food:</h2>
            <input class="bg-neutral-300" type="text" name="" id="food-input" />
          </div>
          <div class="block mb-2">
            <h2 class="inline text-base font-medium">Rent:</h2>
            <input class="bg-neutral-300" type="text" name="" id="rent-input" />
          </div>
          <div class="block mb-2">
            <h2 class="inline text-base font-medium">Clothes:</h2>
            <input class="bg-neutral-300" type="text" name="" id="clothes-input" />
          </div>
          <button onclick="expenseCalculation()" class="px-4 py-2 my-2 rounded-sm bg-sky-500 text-white">
                    Calculate
                  </button>
          <h3 class="text-center font-semibold text-lg my-2">
            Total Expenses: <span id="expense">5500</span>
          </h3>
          <h3 class="text-center font-semibold text-lg my-2">
            Balance: <span id="balance">4500</span>
          </h3>
          <div class="block mb-2">
            <h2 class="inline text-base font-medium">Save:</h2>
            <input class="bg-neutral-300 w-14" type="text" name="" id="save-input" />
            <span class="font-semibold text-lg">%</span>
            <button class="px-2 py-1 my-2 rounded-sm bg-sky-500 text-white">
                      Save
                    </button>
            <h3 class="text-center font-semibold text-lg my-2">
              Saving amount: 2000
            </h3>
            <h3 class="text-center font-semibold text-lg my-2 pb-4">
              Remaining balance: 2500
            </h3>
          </div>
        </div>
      </div>
    </div>
  </div>
</main>


Solution 1:[1]

It's because calculationReuse clears all the inputs in expneseInput.value = "";.

You're calling expenseAndBalance twice with different textIds. The first call works as expected, clears all the inputs because of the reason above, and then when the second expenseAndBalance("balance") happens, all the expense/balnce inputs are empty, leading to NaN parseFloat values.

What I'd suggest is remove expneseInput.value = ""; from calculationReuse and putting it in the original click event function like so:

function expenseCalculation() {
  expenseAndBalance("expense");
  expenseAndBalance("balance");
  clearInputs();
}

function clearInputs() {
document.getElementById('income-input').value = '';
document.getElementById('food-input').value = '';
document.getElementById('rent-input').value = '';
document.getElementById('clothes-input').value = '';
}

function calculationReuse(inputId) {
  const expneseInput = document.getElementById(inputId);
  const expneseInputValue = expneseInput.value;
  return parseFloat(expneseInputValue);
}

This way, you only clear all the inputs once you're done calculating things the way you need to.

Solution 2:[2]

You first call expenseAndBalance to calculate expense, clear the input fields to "" in calculationReuse, and call it again to calculate balance. When expenseAndBalance runs for the second time, all the input fields have the value set to "", hence NaN.

I see no reason to do the entire calculation twice. You calculate both totalExpense and balance in both function calls. Better to update both fields at once in a single function call.

function expenseCalculation() {

  expenseAndBalance();

}

// expense calculation shared function
function calculationReuse(inputId) {
  const expneseInput = document.getElementById(inputId);
  const expneseInputValue = expneseInput.value;
  const expenseAmount = parseFloat(expneseInputValue);
  expneseInput.value = "";
  return expenseAmount;
}
// Getting Total expenses & balance Text
function expenseAndBalance() {
  const income = calculationReuse("income-input");
  const foodExpense = calculationReuse("food-input");
  const rentExpnese = calculationReuse("rent-input");
  const clothesExpense = calculationReuse("clothes-input");

  const totalExpense = foodExpense + rentExpnese + clothesExpense;
  const balance = income - totalExpense;


  document.getElementById("expense").innerText = totalExpense;

  document.getElementById("balance").innerText = balance;

}
<header>
  <h1 class="text-3xl font-semibold text-emerald-500 text-center mt-12 heading">
    Expense Tracker ?
  </h1>
</header>
<main>
  <!-- Image part -->
  <div class="grid grid-cols-2 gap-4 mt-12 mx-8 media-query">
    <div class="money-pic">
      <img src="images/coins-paper-money-globe-white-statistic-form-background.jpg" alt="" />
    </div>
    <!-- Calculation part -->
    <div class="calculation-part bg-slate-200">
      <div class="texts-and-inputs mx-auto">
        <h3 class="text-center font-semibold text-lg my-4">Income</h3>

        <div class="calculation-inputs text-center">
          <h2 class="inline text-base font-medium">Income:</h2>
          <input class="bg-neutral-300" type="text" name="" id="income-input" />
          <h3 class="text-center font-semibold text-lg my-4">Expenses</h3>
          <div class="block mb-2">
            <h2 class="inline text-base font-medium">Food:</h2>
            <input class="bg-neutral-300" type="text" name="" id="food-input" />
          </div>
          <div class="block mb-2">
            <h2 class="inline text-base font-medium">Rent:</h2>
            <input class="bg-neutral-300" type="text" name="" id="rent-input" />
          </div>
          <div class="block mb-2">
            <h2 class="inline text-base font-medium">Clothes:</h2>
            <input class="bg-neutral-300" type="text" name="" id="clothes-input" />
          </div>
          <button onclick="expenseCalculation()" class="px-4 py-2 my-2 rounded-sm bg-sky-500 text-white">
                    Calculate
                  </button>
          <h3 class="text-center font-semibold text-lg my-2">
            Total Expenses: <span id="expense">5500</span>
          </h3>
          <h3 class="text-center font-semibold text-lg my-2">
            Balance: <span id="balance">4500</span>
          </h3>
          <div class="block mb-2">
            <h2 class="inline text-base font-medium">Save:</h2>
            <input class="bg-neutral-300 w-14" type="text" name="" id="save-input" />
            <span class="font-semibold text-lg">%</span>
            <button class="px-2 py-1 my-2 rounded-sm bg-sky-500 text-white">
                      Save
                    </button>
            <h3 class="text-center font-semibold text-lg my-2">
              Saving amount: 2000
            </h3>
            <h3 class="text-center font-semibold text-lg my-2 pb-4">
              Remaining balance: 2500
            </h3>
          </div>
        </div>
      </div>
    </div>
  </div>
</main>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Azarro
Solution 2 cSharp