0

I have 2 inputs that only accepts positive floats with 2 decimals (other characters should be removed by change() function).

When the value of an input is changed, the value of the other input is automatically changed too.


Issue #1 - Main problem

My regex does not block beyond 2 decimals and allow severals . (eg: 12.345.67 sadly works).

Issue #2

Forbidden chars are not properly removed on the call of change(). I get

Error: $scope.uc.replace is not a function

This occurs because replace() only works on strings, and math operators (+, -, *, /) only works on numbers. I need to use both, how to deal with it?


Here is my code, you can use this JSFiddle if you want to try it yourself.

var myApp = angular.module('myApp',[]);

function MyCtrl($scope) {
    $scope.coeff = 0.5;
    $scope.uf = '25';
    $scope.uc = '';
    
    $scope.change = function(type) {
        console.log(type, "changes!");
        
        $scope.uf = $scope.uf.replace(',', '.');
        $scope.uf = $scope.uf.replace(/[^\d.-]/g, '');
        $scope.uc = $scope.uc.replace(',', '.');
        $scope.uc = $scope.uc.replace(/[^\d.-]/g, '');
        
        if(type == 'uf') {
            $scope.uc = $scope.uf * $scope.coeff;
        } else if(type == 'uc') {
            $scope.uf = $scope.uc / $scope.coeff;
        }
    }
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="myApp" ng-controller="MyCtrl">
  <input type="text" ng-model="uf" ng-change="change('uf')"/>
  <input type="text" ng-model="uc" ng-change="change('uc')"/>
</div>
Mistalis
  • 17,793
  • 13
  • 73
  • 97

2 Answers2

0

For Issue #1, here is a regex that filter exactly what you want:

$scope.uf = $scope.uf.replace(',', '.')
                     .replace(/[^\d.]/g, '')
                     .replace(/\./, "x")
                     .replace(/\./g, "")
                     .replace(/x/, ".");

For Issue #2 I made the calculation in parseFloat:

$scope.uc = +parseFloat($scope.uf * $scope.coeff).toFixed(2);
$scope.uf = +parseFloat($scope.uf = $scope.uc / $scope.coeff).toFixed(2);

toFixed(2) allows only 2 decimals after ..


Finally, I put the code checking floats in a directive:

angular.module('myApp').directive('floatOnly', function() {
    return {
        require: 'ngModel',
        restrict: 'A',
        link: function(scope, element, attrs, modelCtrl) {
            modelCtrl.$parsers.push(function(inputValue) {
                if(inputValue === undefined) return '';

                cleanInputValue = inputValue.replace(',', '.')
                                            .replace(/[^\d.]/g, '')
                                            .replace(/\./, "x")
                                            .replace(/\./g, "")
                                            .replace(/x/, ".");
                if(cleanInputValue != inputValue) {
                    modelCtrl.$setViewValue(cleanInputValue);
                    modelCtrl.$render();
                }
                return cleanInputValue;
            });
        }
    }
});

Used in HTML like this:

<div ng-controller="MyCtrl">
  <input type="text" ng-model="uf" ng-change="change('uf')" float-only/>
  <input type="text" ng-model="uc" ng-change="change('uc')" float-only/>
</div>

So change() function now looks like this:

$scope.change = function(type) {
    console.log(type, "changes!");
  
    if(type == 'uf') {
        $scope.uc = +parseFloat($scope.uf * $scope.coeff).toFixed(2);
    } else if(type == 'uc') {
       $scope.uf = +parseFloat($scope.uf = $scope.uc / $scope.coeff).toFixed(2);
    }
 }

Working Fiddle

Community
  • 1
  • 1
Mistalis
  • 17,793
  • 13
  • 73
  • 97
0

What about using input type="number" instead? http://jsfiddle.net/Lvc0u55v/7192/

<div ng-controller="MyCtrl">
  <input type="number" step="0.01" ng-model="uf" ng-change="change('uf')"/>
  <input type="number" step="0.01" ng-model="uc" ng-change="change('uc')"/>
</div>

var myApp = angular.module('myApp',[]);

function MyCtrl($scope) {
    $scope.coeff = 0.5;
    $scope.uf = "25";
    $scope.uc = "";

    $scope.change = function(type) {
        console.log(type, "changes!");

        if(type == 'uf') {
            $scope.uc = $scope.uf * $scope.coeff;
        } else if(type == 'uc') {
            $scope.uf = $scope.uc / $scope.coeff;
              }
    }
}
tomek550
  • 470
  • 4
  • 15
  • `type="number"` does not FORBID to enter non-numeric characters. Here I want to prevent user to enter non-float... :) – Mistalis Jul 21 '16 at 06:48