(function(){

    angular.module("plunker", [])
    
    .controller('MainCtrl', function($scope) {
      $scope.name;
    })
    
})();
<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script data-require="angular.js@1.4.x" src="https://code.angularjs.org/1.4.9/angular.js" data-semver="1.4.9"></script>
    <script src="app.js"></script>
    <script src="max-numbers.service.js"> </script>
    <script src="max-numbers.directive.js"> </script>
  </head>

  <body ng-controller="MainCtrl">
    
    <style>
      input.ng-invalid{
        background-color: red;
      }
    </style>
    
      <strong>Characters can not be inserted : </strong> <br>
      max-numbers : 5 ( - decimals if declared) <br>
      decimals : 2 <br>
      <strong>Validation : </strong>  <br>
      min : 0 <br>
      max : 32.89 <br>
    
    <hr>
    
    <form name="form">
      Only accepts numbers : <br>
      <input type="text" ng-model="name" name="name" max-numbers="16" decimals="3" min="0" max="999999999.999" > 
      <br />
      <button type="submit"> Submit </button>
    </form>
    
    
    
    <hr>
    
    {{ name }}
    
    
  </body>

</html>
(function(){
  


angular.module("plunker")

.factory("MaxNumbersService", [function(){

  /**
   * Contructor
   */
  function MaxInteger(val, allowedIntegerLength, allowedDecimalLength){
      this.val = val;
      this.pointIndex = val.indexOf(".");
      this.integersLength = (this.pointIndex !== -1) ? (val.substring(0, this.pointIndex)).length : val.length;
      //TODO what if finishes by a point
      this.decimalsLength = (this.pointIndex !== -1) ? (val.substring(this.pointIndex + 1)).length : 0;

      this.allowedIntegerLength = allowedIntegerLength;
      this.allowedDecimalLength = allowedDecimalLength;

      this.hasChanged = false;
  }

  MaxInteger.prototype.isNotANumber = function(){
      return isNaN(Number(this.val));
  };

  MaxInteger.prototype.handleIsNaN = function(){
      while(true){
          if(isNaN(Number(this.val))){
              this.val = this.val.substr(0, this.val.length - 1);
          } else{
              break;
          }
      }
      this.hasChanged = true;
  };

  MaxInteger.prototype.throwDecimals = function(){
      var incrementer = (this.allowedDecimalLength) ? this.allowedDecimalLength + 1 : 0;
      this.val = this.val.substring(0, this.pointIndex + incrementer);
      this.hasChanged = true;
  };

  MaxInteger.prototype.hasDecimals = function(){
      return this.val.indexOf(".") !== -1;
  };

  MaxInteger.prototype.hasTooMuchDecimals = function(){
      return this.decimalsLength > this.allowedDecimalLength;
  };

  MaxInteger.prototype.hasTooMuchIntegers = function(){
      return this.integersLength > this.allowedIntegerLength;
  };

  MaxInteger.prototype.throwIntegers = function(){
      var integersLength = this.allowedIntegerLength;
      if(this.pointIndex !== -1){
          integersLength = (this.pointIndex <= this.allowedIntegerLength) ? this.pointIndex : this.allowedIntegerLength;
          this.val = this.val.substr(0, integersLength);
      } else{
          this.val = this.val.substr(0, integersLength);
      }

      this.hasChanged = true;
  };

  MaxInteger.prototype.didItChanged  = function(){
      return this.hasChanged;
  };

  return MaxInteger;


}]);

})();
(function(){
  
angular.module("plunker")


.directive("maxNumbers", ["MaxNumbersService", function(MaxNumbersService){
  return {
      require : "ngModel",
      link : function(scope, element, attrs, modelCtrl){


          //parseInt removes spaces or ennucessary chars. To allow any falsy number
          var maxLength = parseInt(attrs.maxNumbers);
          var allowedIntegerLength = maxLength;
          var allowedDecimalLength = 0;

          if("decimals" in attrs){
              allowedDecimalLength = parseInt(attrs.decimals);
              allowedIntegerLength = maxLength - allowedDecimalLength;
          }

          if("min" in attrs){
              var minimumValue = parseFloat(attrs.min);
              modelCtrl.$validators.min = min;
          }

          if("max" in attrs){
              var maximumValue = parseFloat(attrs.max);
              modelCtrl.$validators.max = max;
          }




          modelCtrl.$parsers.unshift(function(val){
              var maxInteger = new MaxNumbersService(val, allowedIntegerLength, allowedDecimalLength);

              if(maxInteger.isNotANumber()){
                  maxInteger.handleIsNaN();
              }

              if(maxInteger.hasDecimals()){
                  if(allowedDecimalLength){
                      if(maxInteger.hasTooMuchDecimals()){
                          maxInteger.throwDecimals();
                      }
                  } else{
                      maxInteger.throwDecimals();
                  }
              }

              if(maxInteger.hasTooMuchIntegers()){
                  maxInteger.throwIntegers();
              }

              if(maxInteger.didItChanged()){
                  modelCtrl.$setViewValue(maxInteger.val);
              }

              modelCtrl.$render();
              return maxInteger.val;
          });

          modelCtrl.$parsers.unshift(function(view){
              return String(view);
          });

          modelCtrl.$parsers.push(function(view){
              if(!view) return view;
              return Number(view);
          });

          if(!("simpleLink") in attrs){
              modelCtrl.$formatters.unshift(function(val){
                  if(!val) return val;
                  return String(val);
              });

              modelCtrl.$formatters.push(function(val){
                  //On load, this pipeline is always called because view needs to has model
                  if(!val) return val;

                  var maxInteger = new MaxNumbersService(val, allowedIntegerLength, allowedDecimalLength);

                  if(maxInteger.isNotANumber()){
                      maxInteger.handleIsNaN();
                  }

                  if(maxInteger.hasDecimals()){
                      if(allowedDecimalLength){
                          if(maxInteger.hasTooMuchDecimals()){
                              maxInteger.throwDecimals();
                          }
                      } else{
                          maxInteger.throwDecimals();
                      }
                  }

                  if(maxInteger.hasTooMuchIntegers()){
                      maxInteger.throwIntegers();
                  }

                  if(maxInteger.didItChanged()){
                      modelCtrl.$setViewValue(val);
                  }
                  return maxInteger.val;
              });
          }

          function min(model){
              return model ? model >= minimumValue : true;
          }

          function max(model){
              return model ? model <= maximumValue  : true;
          }

      }
  };
}]);

})();