The Code for Loan Calculator
// CONTROLLER FUNCTION(S)
// Get UI values
function getValues() {
let loanValue = document.getElementById("loanValue").value;
let monthsValue = document.getElementById("monthsValue").value;
let rateValue = document.getElementById("rateValue").value;
// convert to Numbers
loanValue = Number(loanValue);
monthsValue = Number(monthsValue);
rateValue = Number(rateValue);
// if valid input, calculate loan payments and display
if (validateInput(loanValue, monthsValue, rateValue)) {
let results = getPayments(loanValue, rateValue, monthsValue);
displayResults(results);
}
}
// LOGIC FUNCTION(S)
function getPayments(amount, rate, term) {
let loanPaymentObj = {};
loanPaymentObj.Payments = [];
loanPaymentObj.Payment = calcPayment(amount, rate, term);
// first month
let balance = amount;
let totalInterest = 0.0;
let monthlyInterest = 0.0;
let monthlyPrincipal = 0.0;
let monthlyRate = calcMonthlyRate(rate);
// loop over each month until term of loan
for (let index = 1; index <= term; index++) {
monthlyInterest = calcMonthlyInterest(balance, monthlyRate);
totalInterest += monthlyInterest;
monthlyPrincipal = loanPaymentObj.Payment - monthlyInterest;
balance -= monthlyPrincipal;
let paymentObj = {};
paymentObj.Month = index;
paymentObj.Payment = loanPaymentObj.Payment;
paymentObj.MonthlyPrincipal = monthlyPrincipal;
paymentObj.MonthlyInterest = monthlyInterest;
paymentObj.TotalInterest = totalInterest;
paymentObj.Balance = balance;
loanPaymentObj.Payments.push(paymentObj);
}
loanPaymentObj.TotalInterest = totalInterest;
loanPaymentObj.TotalCost = amount + totalInterest;
loanPaymentObj.Amount = amount;
return loanPaymentObj;
}
function calcPayment(amount, rate, term) {
let monthlyRate = calcMonthlyRate(rate);
let payment = (amount * monthlyRate) / (1 - Math.pow(1 + monthlyRate, -term));
return payment;
}
function calcMonthlyRate(rate) {
return rate/1200;
}
function calcMonthlyInterest(balance, monthlyRate) {
return balance * monthlyRate;
}
function validateInput(loanValue, monthsValue, rateValue) {
let output = true;
// months is integer
if (!Number.isInteger(monthsValue)) {
alert("Term length (months) must be an integer!")
output = false;
}
// check values are greater than 0
if (loanValue <= 0 || monthsValue <= 0 || rateValue <= 0) {
alert("You must enter a value greater than 0!")
output = false;
}
// check loan upper limit
if (loanValue > 1000000) {
alert("Maximum loan value is £1,000,000")
output = false;
}
// check months upper limit
if (monthsValue > 600) {
alert("Maximum term length is 600 months")
output = false;
}
// check rate upper limit
if (rateValue > 100) {
alert("Maximum rate is 100%")
output = false;
}
return output;
}
// VIEW FUNCTION(S)
function displayResults(results) {
// display results overview
let monthlyPayments = document.getElementById("monthlyPaymentsValue");
let totalPrincipal = document.getElementById("totalPrincipalValue");
let totalInterest = document.getElementById("totalInterestValue");
let totalCost = document.getElementById("totalCostValue");
monthlyPayments.innerHTML = results.Payment.toLocaleString('en-UK', { style: 'currency', currency: 'GBP' });
totalPrincipal.innerHTML = results.Amount.toLocaleString('en-UK', { style: 'currency', currency: 'GBP' });
totalInterest.innerHTML = results.TotalInterest.toLocaleString('en-UK', { style: 'currency', currency: 'GBP' });
totalCost.innerHTML = results.TotalCost.toLocaleString('en-UK', { style: 'currency', currency: 'GBP' });
//TABLE
// get the table body element from the page
let tableBody = document.getElementById("results");
// get the template row
let templateRow = document.getElementById("loanTemplate");
// clear the table first
tableBody.innerHTML="";
results.Payments.forEach(element => {
let tableRow = document.importNode(templateRow.content, true);
let rowCols = tableRow.querySelectorAll("td");
rowCols[0].textContent = element.Month;
rowCols[1].textContent = element.Payment.toLocaleString('en-UK', { style: 'currency', currency: 'GBP' });
rowCols[2].textContent = element.MonthlyPrincipal.toLocaleString('en-UK', { style: 'currency', currency: 'GBP' });
rowCols[3].textContent = element.MonthlyInterest.toLocaleString('en-UK', { style: 'currency', currency: 'GBP' });
rowCols[4].textContent = element.TotalInterest.toLocaleString('en-UK', { style: 'currency', currency: 'GBP' });
rowCols[5].textContent = element.Balance.toLocaleString('en-UK', { style: 'currency', currency: 'GBP' });
tableBody.appendChild(tableRow);
});
}
The Code is structured into seven functions.
getValues
This functions retrieves the user input from the page with getElementById, and converts the inputs to a number type. The inputs are validated with the validateInput function, and if they are valid, the getPayments and displayResults functions are executed.
getPayments
This is the main function of the app, which takes in three arguments that are the three inputs from the user. The function creates an object for the loan which has five parameters to store the required information. The '.Payments' parameter is an array of an additional object which is the payment information for each individual month, and in turn has six parameters itself. The function uses a 'for loop' to loop over the term period and make the necessary function calls to calculate the required loan information.
calcPayment
This function calculates the regular monthly payment amount and used the 'Math.pow' function.
calcMonthlyRate
This function calculated the monthly rate from the annual interest rate.
calcMonthlyInterest
This function calculates the interest in a given month.
validateInput
This function takes in three parameters which are the user inputs. The function uses 'if statements' to determine if the values are appropriate. If the user inputs are found to be problematic, the function returns a boolean false value.
displayResults
displayResults takes in one parameter, a results object. The tables where the results are to be inserted and a template structure of the HTML rows are retrieved from the document using getElementById. A 'foreach' loop iterates over each element in the '.Payments' parameter of the results object, and inserts the corresponding results to the table, using the appendChild function.