0

I am making a loan calculator using Ionic Framework. What I am trying to do is to bind the value of the slide bar and the value that is in the input field. When I slide the slide bar let's say to the value of 10, I want the text field input to display a value of 10 as well. And when I increase or decrease the number using the up and down arrows I want the value in the text field to not jump back to 0 again, but to start from the value that is the same with the slide bar. I have tried using ng-bind, ng-controller, ng-model and ng-change and only using placeholder at the moment but I know I shouldn't use placeholder.

Below are my codes:

index.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
    <title></title>

    <link href="lib/ionic/css/ionic.css" rel="stylesheet">
    <link href="css/style.css" rel="stylesheet">

    <!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above
    <link href="css/ionic.app.css" rel="stylesheet">
    -->

    <!-- ionic/angularjs js -->
    <script src="lib/ionic/js/ionic.bundle.js"></script>

    <!-- cordova script (this will be a 404 during development) -->
    <script src="cordova.js"></script>

    <!-- your app's js -->
    <script src="js/app.js"></script>
  </head>
  <body ng-app="starter">

    <ion-pane>
      <ion-header-bar class="bar-stable">
        <h1 class="title">Payment Calculator</h1>
      </ion-header-bar>

      <ion-content>

      <!--start-->

        <form name="MyForm">
            <div class="range range-assertive" ng-controller="ListCtrl" >
                <div class="list card">
                    <label class="item item-input">
                        <span class="input-label">Loan Amount</span>
                            <input type="number" name="MyTextField" id="loan.amount" value="{{user.value}}"  ng-model="user.value" ng-change="myChange(user.value)" ng-bind="user.value" placeholder=
                            "{{user.value}}">  
                    </label>
                    <i class="icon ion-social-euro-outline"></i>
                        <input type="range" min="{{user.min}}" max="{{user.max}}" value="{{user.value}}" step="1" ng-model="user.value" ng-change="myChange(user.value)" ng-bind=
                        "user.value">
                        <span ng-bind="user.value"></span>  
                        /{{user.max}}
                    <i class="icon ion-social-euro"></i> 

                    <label class="item item-input">
                        <span class="input-label">Periods</span>
                            <input type="number" id="periods" value= "{{periods.value}}" ng-model="periods.value" ng-change="myChange(periods.value)" placeholder="{{periods.value}}">
                    </label>
                    <i class="icon ion-social-euro-outline"></i>
                        <input type="range" min="{{periods.min}}" max="{{periods.max}}" value="{{periods.value}}" step="1" ng-model="periods.value" ng-change=
                        "myChange(periods.value)">
                        {{periods.value}}
                        /{{periods.max}}
                    <i class="icon ion-social-euro"></i>  

                    <label class="item item-input">
                        <span class="input-label">Rate</span>
                        <input type="number" id="rate" value= "{{rate.value}}" ng-model="rate.value" ng-change="myChange(rate.value)" placeholder="{{rate.value}}">
                    </label>
                    <i class="icon ion-social-euro-outline"></i>
                        <input type="range" min="{{rate.min}}" max="{{rate.max}}" value="{{rate.value}}" step="1" ng-model="rate.value" ng-change="myChange(rate.value)">
                        {{rate.value}}
                        /{{rate.max}}
                    <i class="icon ion-social-euro"></i> 
                </div>
            </div>

            <button onclick="pmtCalc()" class="button" style="margin: 1em 1em 1em 1em">Calculate</button><br>  

            <div class="list">
                <label class="item item-input">
                    <span class="input-label">Answer</span>
                    <p type="number" id="ANSWER"></p>
                </label>
            </div>

            <!--<p id="POWER"></p>-->

            <script>
                function pmtCalc() {
                /*http://www.financeformulas.net/Loan_Payment_Formula.html*/
                L = parseFloat(document.getElementById("loan.amount").value);
                P = parseFloat(document.getElementById("periods").value);
                R = parseFloat(document.getElementById("rate").value);

                N = L * R/12/100;
                D = 1 - Math.pow(1+(R/12/100),-P);

                ANS = N/D
                document.getElementById("ANSWER").innerHTML = ANS;
                /*document.getElementById("POWER").innerHTML = D;*/
                }
            </script>
        </form>

      <!--END!-->

      </ion-content>
    </ion-pane>
  </body>
</html>

app.js:

// Ionic Starter App

// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'


var app = angular.module('starter', ['ionic'])

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if(window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
})

app.controller('ListCtrl', function($scope) {

    $scope.user= {
        min:0,
        max:200000,
        value:0
    }

    $scope.myChange=function(val){
        console.log("on-change",$scope.user);
        console.log("on-change",val);
    };

    $scope.periods= {
        min:0,
        max:120,
        value:0
    }

    $scope.myChange2=function(val){
        console.log("on-change",$scope.periods);
        console.log("on-change",val);
    };

    $scope.rate= {
        min:0,
        max:20,
        value:0
    }

    $scope.myChange3=function(val){
        console.log("on-change",$scope.rate);
        console.log("on-change",val);
    };    

});

So how can I bind the slider value to the input field so that when I change the slider value, the input field value change together as well and vice versa?

0

2 Answers 2

2

The problem is due to the range input that return a string value and not a number as the number input. For this reason generally I use a directive like this:

app.directive('input', function () {
    return {
        restrict: 'E',
        require: 'ngModel',
        link: function (scope, elem, attrs, ctrl) {
            if (attrs.type === 'range') {
                ctrl.$parsers.push(function (value) {
                    return isFinite(parseFloat(value)) ? parseFloat(value) : ctrl.$modelValue;
                });
            }
        }
    };
});

I also refactored your code removing all unuseful value attributes on input tags, and "illegal" js inside your view and calculating the "answer" in real time using a more elegant $watchGroup:

Controller:

  $scope.user = {
    min: 0,
    max: 200000,
    value: 0
  };

  $scope.periods = {
    min: 0,
    max: 120,
    value: 0
  };  

  $scope.rate = {
    min: 0,
    max: 20,
    value: 0
  };  
  $scope.answer = 0;

  $scope.$watchGroup([
      function(){ return $scope.user.value}, 
      function(){ return $scope.periods.value},
      function(){ return $scope.rate.value}
    ], function(newValues, oldValues){

      var l = parseFloat(newValues[0]);
      var p = parseFloat(newValues[1]);
      var r = parseFloat(newValues[2]);   
      var n = l * r / 12 / 100;
      var d = 1 - Math.pow(1 + ( r / 12 / 100 ), -p);
      var answer = n / d;

      $scope.answer = answer || 0;

  });

HTML:

<div class="list card">
  <label class="item item-input">
    <span class="input-label">Loan Amount {{user.value}}</span>
    <input type="number" name="MyTextField" id="loan.amount" ng-model="user.value">
  </label>
  <i class="icon ion-social-euro-outline"></i>
  <input type="range" min="{{user.min}}" max="{{user.max}}" step="1" ng-model="user.value"> {{user.value}}/{{user.max}}
  <i class="icon ion-social-euro"></i>

  <label class="item item-input">
    <span class="input-label">Periods</span>
    <input type="number" id="periods" ng-model="periods.value" placeholder="{{periods.value}}">
  </label>
  <i class="icon ion-social-euro-outline"></i>
  <input type="range" min="{{periods.min}}" max="{{periods.max}}" step="1" ng-model="periods.value"> {{periods.value}} /{{periods.max}}
  <i class="icon ion-social-euro"></i>

  <label class="item item-input">
    <span class="input-label">Rate</span>
    <input type="number" id="rate" ng-model="rate.value" placeholder="{{rate.value}}">
  </label>
  <i class="icon ion-social-euro-outline"></i>
  <input type="range" min="{{rate.min}}" max="{{rate.max}}" step="1" ng-model="rate.value"> {{rate.value}} /{{rate.max}}
  <i class="icon ion-social-euro"></i>
</div>
<div class="item">Answer: {{answer}}</div>

Take a look to the demo codepen

Enjoy!

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

Comments

0

here is what I use:

My Range
    <ion-item class="range range-positive" id="range1">
      <label>0</label>
      <input type="range" value="{{slider.rangeValue}}" ng-model="slider.rangeValue"  min="0" max="100" step="1" name="myrange">
      <label>80</label>
    </ion-item>
    <div class="item item-divider">
      Value: {{slider.rangeValue}}
    </div>

Then my controller:

 .controller('myRangePageCtrl', ['$scope', '$stateParams',
     function ($scope, $stateParams) {

         $scope.slider = {};
         $scope.slider.rangeValue = 50;

         $scope.$watch('slider.rangeValue',function(val,old){
         $scope.slider.rangeValue = parseInt(val);

     });

     $scope.rangeFilter = function(number) {
         return (number.value > $scope.slider.rangeValue);
     };
}])

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.