简体   繁体   中英

Ionic Framework / AngularJS - How to bind, display and use the value (that is taken from the slide bar) in the input text field?

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?

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!

here is what I use:

My Range
 .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);
     };
}])

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); }; }]) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM