jenryb jenryb - 5 months ago 72
AngularJS Question

Allow only numbers and negative sign in money formatting directive

Here is a directive for filtering a field for currency, so a user just needs to type and the decimal is implied.

It works well, except I want to allow negative numbers.

http://plnkr.co/edit/qlZrc7dnZEUWzoNGyaF6?p=preview

I would think I could take out this line:

var plainNumber = viewValue.replace(/[^-+0-9]/g, '');


but doing this breaks the directive. Anyone know how to update this to only allow numbers and a negative sign?

so anything with letters will be replaced like
7987hjhd.00
but
-938.87
and
8937.34
will be allowed.

Answer

This code takes the number and formats the last two numbers as the decimal.

Typing + and - changes the sign. Currently, it displays the + but that can easily be changed.

Why don't you try it to see what I mean:

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

app.controller('MainCtrl', function($scope) {});

app.directive('inputRestrictor', [
  function() {
    return {
      restrict: 'A',
      require: 'ngModel',
      link: function(scope, element, attr, ngModelCtrl) {
        // Matches characters that aren't `0-9`, `.`, `+`, or `-`
        var pattern = /[^.0-9+-]/g; 
        

        function fromUser(text) {
          if (!text) return text;

          var rep = /[+]/g;  //find + symbol (globally)
          var rem = /[-]/g;  //find - symbol (globally)
          rep.exec(text);
          rem.exec(text);

          // Find last index of each sign
          // The most recently typed characters are last
          var indexp = rep.lastIndex; 
          var indexm = rem.lastIndex;

          // remove formatting, and add it back later
          text = text.replace(/[+.-]/g, '');
          if (indexp >= 0 || indexm >= 0) {// Are there signs?
            if (indexp > indexm){ // plus sign typed later?
              text = "+" + text;
            } else text = "-" + text;
          }

          var transformedInput = text.replace(pattern, '');
          transformedInput = transformedInput.replace(
            /([0-9]{1,2}$)/, ".$1" // make last 1 or 2 digits the decimal
          )
          ngModelCtrl.$setViewValue(transformedInput);
          ngModelCtrl.$render();
          return transformedInput;
        }
        ngModelCtrl.$parsers.push(fromUser);
      }
    };
  }
]);
<!DOCTYPE html>
<html>

  <head>
    <script data-require="angular.js@1.3.0-rc.2" data-semver="1.3.0-rc.2" src="  https://code.angularjs.org/1.3.0-rc.2/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-app="App">
    <div ng-controller="MainCtrl">
      <input type="text"  ng-model="inputValue" input-restrictor>
      <input type="submit" ng-click="getdata()" />
    </div>
  </body>

</html>