Policy to restrict typing with regular expression in AngularJS

1

I wrote a directive to inhibit typing from specifying a regex. However there are two bugs in this solution:

  • In the first example input should allow only numbers or numbers followed by periods [.] , or followed by periods followed by numbers with no more than 4 digits .
    • If I type '1.1111' and I go to the beginning of the field and type another digit (in order to have the value '.1111' ), nothing happens. This bug occurs because I use the expression elem.val() + event.key in my validator (I used it because I do not know how to retrieve the current value of the input);
  • The second is the fact that some characters (chrome, sharp, tilde, circumflex) are being allowed (press any of them more than once in the field), although regex does not allow them.
  • What changes do I have to make in my code to have an effective constraint from regex?

      <html ng-app="app">    
      <head>
        <script data-require="[email protected]" data-semver="1.6.4" src="https://code.angularjs.org/1.6.4/angular.min.js"></script><linkrel="stylesheet" href="style.css" />
        <script src="script.js"></script>
      </head>
    
      <body>
        <h1>Restrict typing by RegExp</h1>
        PATTERN 1 (^\d+$|^\d+[.]$|^\d+[.]\d{1,4}$) <input type="text" allow-typing="^\d+$|^\d+[.]$|^\d+[.]\d{1,4}$"/><br>
        ONLY NUMBERS <input type="text" allow-typing="^[0-9]+$"/><br>
        ONLY STRINGS <input type="text" allow-typing="^[a-zA-Z]+$"/>
      </body>
    
    </html>
    

    Directive

    angular.module('app', []).directive('allowTyping', function() {
      return {
        restrict: 'A',
        link: function(scope, elem, attrs, ctrl) {
          var regex = attrs.allowTyping;
          elem.bind('keypress', function(event) {
            var input = elem.val() + event.key;
            var validator = new RegExp(regex);
            if(!validator.test(input)) {
              event.preventDefault();
              return false;
            }
          });
        }
      };
    });
    
        
    asked by anonymous 15.01.2018 / 15:18

    1 answer

    3

    To solve the problem (2) of the diacritics:

    <input type="text" allow-typing="^[A-zÀ-ÿ]+$"/>
    

    To solve the problem (1) use timeout and compare the pre- and post-keydown value. But it still allows you to paste wrong values, use onfocus / onclick + onchange for the comparison.

    var regex = attrs.allowTyping;
    var prevValue = elem.val();
    
    elem.bind('keydown', function(event) {
      var validator = new RegExp(regex);
      var prevValue = this.value;
    
      setTimeout(function () {
        if (!validator.test(elem.val()))
          elem.val(prevValue);
      }, 1)
    });
    
    elem.bind('focus click', function(event) {
      var prevValue = this.value;
    });
    
    elem.bind('change', function(event) {
      var validator = new RegExp(regex);
    
      setTimeout(function () {
        console.log(prevValue, elem.val())
        if (!validator.test(elem.val()))
          elem.val(prevValue);
      }, 1)
    });
    
        
    17.01.2018 / 23:22