angularjs验证输入并防止更改(如果无效)

时间:2013-08-14 20:23:06

标签: javascript angularjs angularjs-directive

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

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

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 个答案:

答案 0 :(得分:21)

我最近为此写了一个指令。它需要一个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]*$/">

答案 1 :(得分:6)

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

Get the library并简单地装饰你的输入:

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

GitHub:AlphaGit/ng-pattern-restrict

答案 2 :(得分:4)

您可以随时收听keypress事件并阻止该角色完成。 Here is a plunker

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;
            }
          });
        }
    }   
});

答案 3 :(得分: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);
                }
            });
        }
    }
}]);