4

我需要一个输入字段,我只能在其中输入值 1,2 或 3,因此我正在尝试构建一个指令,如果它与这些值不匹配,它会阻止对模型的所有更改。
例如,值为 1,我将其更改为 5,它应该仍然是 1。

我整理了一个小小提琴http://jsfiddle.net/kannix/Q5YKE/但使用 $parsers 很可能是错误的。

app.directive('myvalidator', function () {
    return {
        require: 'ngModel',
        link: function (scope, elm, attrs, ctrl) {
            var validValues = [1,2,3];
            ctrl.$parsers.push(function (value) {
                if (validValues.indexOf(value) === -1){
                    //what to do here? should refuse wrong value and leave the old one
                }   
            });
        }
    }   

})
4

4 回答 4

24

我最近为此写了一个指令。它需要一个 regExp 对象来验证传入的按键,并且仅在有效时才允许它们:

// forces keystrokes that satisfy the regExp passed
app.directive("regExpRequire", function() {

    var regexp;
    return {
        restrict: "A",
        link: function(scope, elem, attrs) {
            regexp = eval(attrs.regExpRequire);

            var char;
            elem.on("keypress", function(event) {
                char = String.fromCharCode(event.which)
                if(!regexp.test(elem.val() + char))
                    event.preventDefault();
            })
        }
    }

})

模板使用:<input type="text" reg-exp-require="/^[a-zA-Z]$/">

或者在你的情况下:<input type="text" reg-exp-require="/^[1-3]*$/">

于 2013-08-15T02:22:17.090 回答
6

我建议使用该ng-pattern-restrict指令。

获取库并简单地装饰您的输入,如下所示:

<input type="text" pattern="[0-9]+" ng-pattern-restrict />

GitHub:AlphaGit/ng-pattern-restrict

于 2015-12-18T11:11:59.443 回答
4

您可以随时听取keypress事件并阻止角色通过。这是一个笨蛋

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

app.controller('MainCtrl', function($scope) {
  $scope.name = 'World';
  $scope.validValues = ['a','1','2'];
});

app.directive('myValidator', function ($parse) {
    return {
        scope: {
          validValues: '=validValues'
        },
        link: function (scope, elm, attrs) {
          elm.bind('keypress', function(e){
            var char = String.fromCharCode(e.which||e.charCode||e.keyCode), matches = [];
            angular.forEach(scope.validValues, function(value, key){
              if(char === value) matches.push(char);
            }, matches);
            if(matches.length == 0){
              e.preventDefault();
              return false;
            }
          });
        }
    }   
});
于 2013-08-14T21:40:18.063 回答
2

实际上,我必须建立并修改 Ian Haggerty 的答案。他的代码运行良好,直到我开始以不同的方式对其进行测试。我专门尝试测试小于 100 的值,但我得到了一些奇怪的结果。

如果我的输入中有 100,然后尝试插入一个小数使其变为 10.0,Ian 的修复没有考虑到这一点,并说它与我的正则表达式不匹配(即使我允许最多两位小数)。事实证明,它总是附加我在它正在测试的字符串的 END 处按下的字符,即使我将它插入到中间。

我的更改是将原始值存储在“keypress”上,然后存储在“keyup”(或“更改”,如果您愿意)上,它会检查新值。如果无效,则恢复为原始状态。

不幸的是,它确实短暂地更新了模型,但至少它允许您在输入值的中间或开头键入字符,并且仍然正确匹配正则表达式。在 Angular 1.3 中,我们可能可以使用 ng-model-options="{debounce:250}" 来解决这个问题。让任何依赖于这种模型更改的代码都是幂等的,这非常有帮助。

usage: <input ... validate-with="/^([\d]{1,2}\.[\d]{1,2}|\.?[\d]{1,2}|100)?$/" />

.directive("validateWith", [function(){
    return {
        restrict: "A",
        link: function($scope, $el, $attrs){
            var regexp = eval($attrs.validateWith);
            var origVal;
            // store the current value as it was before the change was made
            $el.on("keypress", function(e){
                origVal = $el.val();
            });

            // after the change is made, validate the new value
            // if invalid, just change it back to the original
            $el.on("keyup", function(e){
                if(!regexp.test($el.val())){
                    $el.val(origVal);
                }
            });
        }
    }
}]);
于 2014-06-05T20:41:26.217 回答