How To Create A Graphical Loan Repayment Calculator

Introduction

In this article, we will be creating a  graphical loan repayment calculator using Asp.net webforms, C#, and Javascript.  It is important that when people are applying for loan, they should clearly understand how the loan will be repaid, in terms of installments, interest, total repayment amount, various effects of choosing between different repayment intervals, and many more.

Programming Language

Most of the coding will be done in javascript, we will then place the javascript code inside an asp.net webform.

Javascript that will be embedded into Aspx page

A. Let us first set up the initial variables

<script type="text/javascript">
//initial variables
var loanYear = 20;
var stepYear = 1;
var maxLoanYear = 30;
var paymentCycle = 1;
var monthlyRepayment = 0;
var monthlyInterest = 0;
var amortData = [];

B. Create startup method 

 //start up method
 $(function() {
     $(".ul-buttons li").click(function() {
         $(".ul-buttons li").removeClass("selected");
         $(this).addClass("selected");
         paymentCycle = parseInt($(this).attr("data-value"));
         calculateLoan();
     });
     //Add on blur event
     $("#txtLoan, #txtInterest").on("blur", function() {
         //Perform a check if loan or interest value has been entered invalid value, if it is, set the default value
         if (isNaN($("#txtLoan").val())) {
             $("#txtLoan").val(1000000);
         }
         if (isNaN($("#txtInterest").val())) {
             $("#txtInterest").val(8.99);
         }
         calculateLoan();
     });
 });

C. Create the noUiSlider

//create the noUiSlider
var range = document.getElementById('yearRange');
noUiSlider.create(range, {
    range: {
        'min': 1,
        'max': maxLoanYear
    },
    step: stepYear,
    start: [loanYear],
    margin: 300,
    connect: true,
    direction: 'ltr',
    orientation: 'horizontal',
    pips: {
        mode: 'steps',
        stepped: false,
        density: 2
    }
});
//Add the change event to redraw the graph and calculate loan
range.noUiSlider.on("change", function(value) {
    loanYear = parseInt(value[0]);
    calculateLoan();
});

D. Create the Chart    

 //Chart
 google.charts.load('current', {
     'packages': ['corechart']
 });

 function drawChart() {
     //Hold the loan data array
     var loanData = [];
     var dt = new Date();
     var yearCounter = 1;
     //Add the graph header
     var headerData = ['Year', 'Interest', 'Interest & Principal', 'Balance'];
     loanData.push(headerData);
     for (var i = dt.getFullYear(); i < dt.getFullYear() + loanYear; i++) {
         loanData.push([i.toString(), getAmortData("interest", 12 * yearCounter), monthlyRepayment * 12 * yearCounter, getAmortData("balance", 12 * yearCounter)]);
         yearCounter++;
     }
     var data = google.visualization.arrayToDataTable(loanData);
     var options = {
         title: 'Loan Chart',
         hAxis: {
             title: 'Year',
             titleTextStyle: {
                 color: '#333'
             }
         },
         vAxis: {
             minValue: 0
         },
         pointsVisible: true
     };
     var chart = new google.visualization.AreaChart(document.getElementById('graph-chart'));
     chart.draw(data, options);
 }

E. Get amortization data based on type and terms

function getAmortData(dataType, terms) {
    var dataValue = 0;
    switch (dataType) {
        case "interest":
            for (var i = 0; i < terms; i++) {
                dataValue += parseFloat(amortData[i].Interest);
            }
            break;
        case "balance":
            dataValue = parseFloat(amortData[terms - 1].Balance);
            break;
    }
    return Math.round(dataValue);
}

F. Create calculate function   

//calculate function
function calculateLoan() {
    $("#year-value").html(loanYear);
    var loanBorrow = parseFloat($("#txtLoan").val());
    var interestRate = parseFloat($("#txtInterest").val()) / 1200;
    var totalTerms = 12 * loanYear;
    //Monthly
    var schedulePayment = Math.round(loanBorrow * interestRate / (1 - (Math.pow(1 / (1 + interestRate), totalTerms))));
    monthlyRepayment = schedulePayment;
    var totalInterestPay = totalTerms * schedulePayment;
    amort(loanBorrow, parseFloat($("#txtInterest").val()) / 100, totalTerms);
    switch (paymentCycle) {
        case 2:
            //Fortnightly
            //we multiple by 12 then divided by 52 then multiple by 2
            schedulePayment = Math.round(((schedulePayment * 12) / 52) * 2);
            break;
        case 3:
            //Weekly
            //we multiple by 12 then divided by 52
            schedulePayment = Math.round((schedulePayment * 12) / 52);
            break;
    }
    $("#repayment-value").html(schedulePayment);
    $("#interest-total").html(getAmortData("interest", totalTerms));
    monthlyInterest = (totalInterestPay - loanBorrow) / totalTerms;
    google.charts.setOnLoadCallback(drawChart);
}
calculateLoan();
//function to calculate the amortization data
function amort(balance, interestRate, terms) {
    amortData = [];
    //Calculate the per month interest rate
    var monthlyRate = interestRate / 12;
    //Calculate the payment
    var payment = balance * (monthlyRate / (1 - Math.pow(1 + monthlyRate, -terms)));
    for (var count = 0; count < terms; ++count) {
        var interest = balance * monthlyRate;
        var monthlyPrincipal = payment - interest;
        var amortInfo = {
            Balance: balance.toFixed(2),
            Interest: balance * monthlyRate,
            MonthlyPrincipal: monthlyPrincipal
        }
        amortData.push(amortInfo);
        balance = balance - monthlyPrincipal;
    }
} < /script>

G. Aspx Page with complete javascript inserted in.

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="loancalculator.aspx.cs" Inherits="cooperativesocietysoftware.loancalculator" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
    <html>
<head>
    <title>Loan Calculator - </title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/12.1.0/nouislider.css" rel="stylesheet">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/12.1.0/nouislider.js"></script>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <style>
        #loan-container {
            text-align: left;
            max-width: 1200px;
            margin: 20px auto;
            box-sizing: border-box;
            font-family: Roboto,Arial,sans-serif;
        }

        .box-pane {
            border: 1px solid #ddd;
            border-radius: 3px;
            padding: 25px;
            box-sizing: border-box;
            min-height: 570px;
        }

        #info-pane {
            float: left;
            width: 35%;
        }

        #graph-pane {
            float: right;
            width: 63%;
        }

        .heading-title {
            font-size: 1.35em;
            margin-bottom: 15px;
        }

        #repayment-total {
            float: left;
            width: 48%;
        }

        #repayment-cycle {
            width: 48%;
            float: right;
            text-align: right;
        }

        .row-input {
            margin-bottom: 20px;
        }

            .row-input label {
                padding: 5px 0;
                display: block;
            }

            .row-input input, .row-input select {
                background-color: #fff;
                border: 1px solid #ddd;
                padding: 9px 15px 10px;
                outline: none;
                border-radius: 5px;
                font-size: 1em;
            }

        .input-wrap {
            position: relative;
        }

        .currency-code {
            position: absolute;
            left: 3px;
            top: 9px;
        }

        .percentage-code {
            position: absolute;
            left: 75px;
            top: 9px;
        }

        .ul-buttons, .ul-buttons li {
            margin: 0;
            padding: 0;
            list-style: none;
        }

            .ul-buttons li {
                float: left;
                background-color: #f1f1f1;
                color: #6e6e6e;
                padding: 8px 25px;
                box-shadow: 0 2px 0 #ddd;
                cursor: pointer;
                font-size: 1rem;
                line-height: 1.5;
                width: 33%;
                float: left;
                box-sizing: border-box;
                text-align: center;
                border-left: solid 1px #ffffff;
                border-right: solid 1px #ffffff;
            }

                .ul-buttons li:hover, .ul-buttons li.selected {
                    background-color: #008094;
                    box-shadow: 0 2px 0 #006575;
                    color: #ffffff;
                }

        .note-text {
            font-size: 0.8em;
            font-style: italic;
            padding-top: 5px;
        }

        .range-slider {
            margin: 15px 0 65px 0;
        }

        .noUi-value {
            margin-top: 4px;
            font-size: 1em;
        }

        .short-input {
            width: 60px;
        }

        .bold {
            font-weight: normal;
        }

        .loan-value {
            font-size: 1.3em;
            font-weight: bold;
        }

        .orange-text {
            color: #f56a00;
        }

        #graph-chart {
            width: 100%;
            height: 450px;
        }

        .clear {
            clear: both;
        }

        @media screen and (max-width: 992px) {
            #info-pane, #graph-pane {
                float: none;
                width: 100%;
                margin-bottom: 20px;
            }

            .box-pane {
                min-height: 500px;
            }
        }
    </style>
</head>
<body>
    <div id="loan-container">
        <div id="info-pane" class="box-pane">
            <div class="heading-title bold">Calculate Your Loan.</div>
            <div class="row-input">
                <label>How much would you like to borrow?</label>
                <div class="input-wrap">
                    <div class="currency-code">N</div>
                    <input type="text" type="number" id="txtLoan" value="1000000" />
                </div>
            </div>
            <div class="row-input">
                <label>Loan interest rate?</label>
                <div class="input-wrap">
                    <div class="percentage-code">%</div>
                    <input type="text" type="number" id="txtInterest" value="8.99" maxlength="5" class="short-input" />
                </div>
            </div>
            <div class="row-input">
                <label>How many years would you like the loan for?</label>
                <div id="yearRange" class="range-slider"></div>
            </div>
            <div class="row-input">
                <label>How often would you like to make payments?</label>
                <ul class="ul-buttons">
                    <li class="selected" data-value="1">Monthly</li>
                    <li data-value="2">Fortnightly</li>
                    <li data-value="3">Weekly</li>
                </ul>
            </div>
        </div>
        <div id="graph-pane" class="box-pane">
            <div id="repayment-total">
                <div class="heading-title bold">Total interest</div>
                <div id="repayment-total-value" class="loan-value">
                    N<span id="interest-total">0</span> over <span class="orange-text"><span id="year-value">5</span> years</span>
                </div>
            </div>
            <div id="repayment-cycle">
                <div class="heading-title bold">Payment would be</div>
                <div id="repayment-cycle-value" class="loan-value">
                    N<span id="repayment-value">0</span> per <span class="orange-text">fortnight</span>
                </div>
            </div>

            <div class="clear"></div>
            <div id="graph-chart"></div>
        </div>
    </div>
<script type="text/javascript">
        //initial variables
        var loanYear = 20;
        var stepYear = 1;
        var maxLoanYear = 30;
        var paymentCycle = 1;
        var monthlyRepayment = 0;
        var monthlyInterest = 0;
        var amortData = [];

        //start up method
        $(function () {
            $(".ul-buttons li").click(function () {
                $(".ul-buttons li").removeClass("selected");
                $(this).addClass("selected");
                paymentCycle = parseInt($(this).attr("data-value"));
                calculateLoan();
            });

            //Add on blur event
            $("#txtLoan, #txtInterest").on("blur", function () {
                //Perform a check if loan or interest value has been entered invalid value, if it is, set the default value
                if (isNaN($("#txtLoan").val())) {
                    $("#txtLoan").val(1000000);
                }

                if (isNaN($("#txtInterest").val())) {
                    $("#txtInterest").val(8.99);
                }
                calculateLoan();
            });
        });

        //create the noUiSlider
        var range = document.getElementById('yearRange');
        noUiSlider.create(range, {
            range: {
                'min': 1,
                'max': maxLoanYear
            },
            step: stepYear,
            start: [loanYear],
            margin: 300,
            connect: true,
            direction: 'ltr',
            orientation: 'horizontal',
            pips: {
                mode: 'steps',
                stepped: false,
                density: 2
            }
        });

        //Add the change event to redraw the graph and calculate loan
        range.noUiSlider.on("change", function (value) {
            loanYear = parseInt(value[0]);
            calculateLoan();
        });

        //Chart
        google.charts.load('current', { 'packages': ['corechart'] });
        function drawChart() {
            //Hold the loan data array
            var loanData = [];

            var dt = new Date();
            var yearCounter = 1;

            //Add the graph header
            var headerData = ['Year', 'Interest', 'Interest & Principal', 'Balance'];
            loanData.push(headerData);

            for (var i = dt.getFullYear(); i < dt.getFullYear() + loanYear; i++) {
                loanData.push([i.toString(), getAmortData("interest", 12 * yearCounter), monthlyRepayment * 12 * yearCounter, getAmortData("balance", 12 * yearCounter)]);
                yearCounter++;
            }

            var data = google.visualization.arrayToDataTable(loanData);

            var options = {
                title: 'Loan Chart',
                hAxis: { title: 'Year', titleTextStyle: { color: '#333' } },
                vAxis: { minValue: 0 },
                pointsVisible: true
            };

            var chart = new google.visualization.AreaChart(document.getElementById('graph-chart'));
            chart.draw(data, options);
        }

        //Get amortization data based on type and terms
        function getAmortData(dataType, terms) {
            var dataValue = 0;
            switch (dataType) {
                case "interest":
                    for (var i = 0; i < terms; i++) {
                        dataValue += parseFloat(amortData[i].Interest);
                    }
                    break;
                case "balance":
                    dataValue = parseFloat(amortData[terms - 1].Balance);
                    break;
            }
            return Math.round(dataValue);
        }

        //calculate function
        function calculateLoan() {
            $("#year-value").html(loanYear);
            var loanBorrow = parseFloat($("#txtLoan").val());
            var interestRate = parseFloat($("#txtInterest").val()) / 1200;
            var totalTerms = 12 * loanYear;

            //Monthly
            var schedulePayment = Math.round(loanBorrow * interestRate / (1 - (Math.pow(1 / (1 + interestRate), totalTerms))));
            monthlyRepayment = schedulePayment;
            var totalInterestPay = totalTerms * schedulePayment;
            amort(loanBorrow, parseFloat($("#txtInterest").val()) / 100, totalTerms);

            switch (paymentCycle) {
                case 2:
                    //Fortnightly
                    //we multiple by 12 then divided by 52 then multiple by 2
                    schedulePayment = Math.round(((schedulePayment * 12) / 52) * 2);
                    break;
                case 3:
                    //Weekly
                    //we multiple by 12 then divided by 52
                    schedulePayment = Math.round((schedulePayment * 12) / 52);
                    break;
            }

            $("#repayment-value").html(schedulePayment);
            $("#interest-total").html(getAmortData("interest", totalTerms));
            monthlyInterest = (totalInterestPay - loanBorrow) / totalTerms;
            google.charts.setOnLoadCallback(drawChart);
        }

        calculateLoan();

        //function to calculate the amortization data
        function amort(balance, interestRate, terms) {
            amortData = [];

            //Calculate the per month interest rate
            var monthlyRate = interestRate / 12;

            //Calculate the payment
            var payment = balance * (monthlyRate / (1 - Math.pow(1 + monthlyRate, -terms)));

            for (var count = 0; count < terms; ++count) {
                var interest = balance * monthlyRate;
                var monthlyPrincipal = payment - interest;
                var amortInfo = {
                    Balance: balance.toFixed(2),
                    Interest: balance * monthlyRate,
                    MonthlyPrincipal: monthlyPrincipal
                }
                amortData.push(amortInfo);
                balance = balance - monthlyPrincipal;
            }

        }
    </script>
</body>
</html>
</asp:Content>

Final Output

How To Create A Graphical Loan Repayment Calculator