Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何向AngularJS表单添加自定义验证?_Angularjs - Fatal编程技术网

如何向AngularJS表单添加自定义验证?

如何向AngularJS表单添加自定义验证?,angularjs,Angularjs,我有一个带有输入字段和验证设置的表单,通过添加required属性等。但对于某些字段,我需要做一些额外的验证。我如何“点击”到FormController控制的验证 自定义验证可能类似于“如果填写了这3个字段,则此字段是必需的,并且需要以特定方式格式化” FormController.$setValidity中有一个方法,但它看起来不像公共API,所以我不想使用它。创建自定义指令并使用NgModelController看起来像是另一个选项,但基本上需要我为每个自定义验证规则创建一个指令,这是我不

我有一个带有输入字段和验证设置的表单,通过添加
required
属性等。但对于某些字段,我需要做一些额外的验证。我如何“点击”到
FormController
控制的验证

自定义验证可能类似于“如果填写了这3个字段,则此字段是必需的,并且需要以特定方式格式化”

FormController.$setValidity
中有一个方法,但它看起来不像公共API,所以我不想使用它。创建自定义指令并使用
NgModelController
看起来像是另一个选项,但基本上需要我为每个自定义验证规则创建一个指令,这是我不想要的


实际上,在最简单的场景中,将控制器中的字段标记为无效(同时保持
FormController
同步)可能是我完成工作所需要的,但我不知道如何做到这一点。

Angular UI的项目包括一个UI验证指令,它可能会帮助您完成这项工作。它允许您指定一个要调用的函数来执行验证

查看演示页面:,向下搜索验证标题

从演示页面:

<input ng-model="email" ui-validate='{blacklist : notBlackListed}'>
<span ng-show='form.email.$error.blacklist'>This e-mail is black-listed!</span>

编辑:在下面添加有关ngMessages(>=1.3.X)的信息。

标准表单验证消息(1.0.X及以上版本) 由于这是Google“Angular Form Validation”的顶级结果之一,目前,我想为来自那里的任何人添加另一个答案

FormController中有一个方法。$setValidity,但它看起来不像公共API,所以我不想使用它

这是“公开的”,不用担心。使用它。这就是它的目的。如果不打算使用它,Angular开发人员会在关闭时将其私有化

要进行自定义验证,如果您不想像其他答案建议的那样使用Angular UI,只需滚动您自己的验证指令即可

app.directive('blacklist',function(){
返回{
要求:'ngModel',
链接:功能(范围、要素、属性、ngModel){
var blacklist=attr.blacklist.split(',');
//对于DOM->模型验证
ngModel.$parsers.unshift(函数(值){
var valid=blacklist.indexOf(值)=-1;
ngModel.$setValidity(“黑名单”,有效);
返回有效?值:未定义;
});
//用于模型->DOM验证
ngModel.$formatters.unshift(函数(值){
ngModel.$setValidity('blacklist',blacklist.indexOf(value)=-1);
返回值;
});
}
};
});
下面是一些示例用法:

<input ng-model="price1" 
       my-test-expression="$model > 0" 
       my-test-expression-watch="price2,someOtherWatchedPrice" />
<input ng-model="price2" 
       my-test-expression="$model > 10" 
       my-test-expression-watch="price1" 
       required />

短语“{data.fruitName}}”被列入黑名单
必修的
提交
注意:在1.2.X中,如果
ng show
替换上述
ng show
,则可能更倾向于使用
ng

这是一份必须的文件

此外,我还写了一些关于这个主题的博客文章,内容更加详细:

编辑:在1.3.X中使用ngMessages 您现在可以使用ngMessages模块而不是ngShow来显示错误消息。它实际上可以处理任何东西,不一定是错误消息,但以下是一些基本信息:

  • 包括
  • 在模块声明中参考
    ngMessages

    var-app=angular.module('myApp',['ngMessages']);
    
  • 添加适当的标记:

    
    必修的
    无效电子邮件
    
  • 在上面的标记中,
    ng message=“personForm.email.$error”
    基本上指定了
    ng message
    子指令的上下文。然后
    ng message=“required”
    ng message=“email”
    指定要查看的上下文的属性最重要的是,它们还指定了将其签入的顺序。它在列表中找到的第一个“truthy”将获胜,它将显示该消息,而不会显示其他消息


    和一个

    您可以使用验证场景所需的ng(“如果填写了这3个字段,则此字段为必填字段”:


    @synergetic我认为@blesh应该将函数验证放在下面

    function validate(value) {
        var valid = blacklist.indexOf(value) === -1;
        ngModel.$setValidity('blacklist', valid);
        return valid ? value : undefined;
    }
    
    ngModel.$formatters.unshift(validate);
    ngModel.$parsers.unshift(validate);
    

    下面是一种在表单(from:)中执行自定义通配符表达式验证的酷方法:

    
    
    app.directive('ensureExpression',['$http','$parse',function($http,$parse){
    返回{
    要求:'ngModel',
    链接:功能(范围、元素、属性、ngModelController){
    范围$watch(attrs.ngModel,函数(值){
    var booleansult=$parse(attrs.ensureExpression)(范围);
    ngModelController.$setValidity('expression',booleansult);
    });
    }
    };
    }]);
    
    (支持表达式命名和多个表达式)

    它类似于“ui验证”
    ,但您不需要特定于范围的验证功能(这通常是有效的),当然,您也不需要这样的ui.utils。

    您可以使用

    示例:使用函数验证字段

    <input  type = "text"
        name = "firstName"
        ng-model = "person.firstName"
        validator = "myCustomValidationFunction(form.firstName)">
    
    您也可以这样做:

    <input  type = "text"
            name = "firstName"
            ng-model = "person.firstName"
            validator = "'!(field1 && field2 && field3)'"
            invalid-message = "'This field is required'">
    
    
    
    (其中field1、field2和field3是范围变量。您可能还需要检查字段是否不等于空字符串)

    如果该字段未通过
    验证程序
    ,则该字段将被标记为无效,用户将无法提交表单

    有关更多用例和示例,请参阅:


    免责声明:我是Angular Validator的作者

    更新:

    <input  type = "text"
            name = "firstName"
            ng-model = "person.firstName"
            validator = "'!(field1 && field2 && field3)'"
            invalid-message = "'This field is required'">
    
    以前指令的改进和简化版本(一个而不是两个),具有相同的功能:

    .directive('myTestExpression', ['$parse', function ($parse) {
        return {
            restrict: 'A',
            require: 'ngModel',
            link: function (scope, element, attrs, ctrl) {
                var expr = attrs.myTestExpression;
                var watches = attrs.myTestExpressionWatch;
    
                ctrl.$validators.mytestexpression = function (modelValue, viewValue) {
                    return expr == undefined || (angular.isString(expr) && expr.length < 1) || $parse(expr)(scope, { $model: modelValue, $view: viewValue }) === true;
                };
    
                if (angular.isString(watches)) {
                    angular.forEach(watches.split(",").filter(function (n) { return !!n; }), function (n) {
                        scope.$watch(n, function () {
                            ctrl.$validate();
                        });
                    });
                }
            }
        };
    }])
    
    示例如何使用它生成交叉验证字段:

    <input name="price1"
           ng-model="price1" 
           ensure-expression="price1 > price2" 
           ensure-watch="price2" />
    <input name="price2" 
           ng-model="price2" 
           ensure-expression="price2 > price3" 
           ensure-watch="price3" />
    <input name="price3" 
           ng-model="price3" 
           ensure-expression="price3 > price1 && price3 > price2" 
           ensure-watch="price1,price2" />
    
    
    
    确保在以下情况下执行表达式
    以验证模型
    <input ng-model="price1" 
           my-test-expression="$model > 0" 
           my-test-expression-watch="price2,someOtherWatchedPrice" />
    <input ng-model="price2" 
           my-test-expression="$model > 10" 
           my-test-expression-watch="price1" 
           required />
    
    .directive('ensureExpression', ['$parse', function($parse) {
        return {
            restrict: 'A',
            require: 'ngModel',
            controller: function () { },
            scope: true,
            link: function (scope, element, attrs, ngModelCtrl) {
                scope.validate = function () {
                    var booleanResult = $parse(attrs.ensureExpression)(scope);
                    ngModelCtrl.$setValidity('expression', booleanResult);
                };
    
                scope.$watch(attrs.ngModel, function(value) {
                    scope.validate();
                });
            }
        };
    }])
    
    .directive('ensureWatch', ['$parse', function ($parse) {
        return {
            restrict: 'A',
            require: 'ensureExpression',
            link: function (scope, element, attrs, ctrl) {
                angular.forEach(attrs.ensureWatch.split(",").filter(function (n) { return !!n; }), function (n) {
                    scope.$watch(n, function () {
                        scope.validate();
                    });
                });
            }
        };
    }])
    
    <input name="price1"
           ng-model="price1" 
           ensure-expression="price1 > price2" 
           ensure-watch="price2" />
    <input name="price2" 
           ng-model="price2" 
           ensure-expression="price2 > price3" 
           ensure-watch="price3" />
    <input name="price3" 
           ng-model="price3" 
           ensure-expression="price3 > price1 && price3 > price2" 
           ensure-watch="price1,price2" />
    
            .directive('invalidIf', [function () {
            return {
                require: 'ngModel',
                link: function (scope, elm, attrs, ctrl) {
    
                    var argsObject = scope.$eval(attrs.invalidIf);
    
                    if (!angular.isObject(argsObject)) {
                        argsObject = { invalidIf: attrs.invalidIf };
                    }
    
                    for (var validationKey in argsObject) {
                        scope.$watch(argsObject[validationKey], function (newVal) {
                            ctrl.$setValidity(validationKey, !newVal);
                        });
                    }
                }
            };
        }]);
    
    <input ng-model="foo" invalid-if="{fooIsGreaterThanBar: 'foo > bar',
                                       fooEqualsSomeFuncResult: 'foo == someFuncResult()'}/>
    
    <input ng-model="foo" invalid-if="foo > bar"/>
    
     <form name="myform" novalidate>
                    <table>
                        <tr>
                            <td><input name='test' type='text' required  ng-model='test' custom-validation></td>
                            <td ng-messages="myform.test.$error"><span ng-message="invalidshrt">Too Short</span></td>
                        </tr>
                    </table>
                </form>
    
    angular.module('myApp',['ngMessages']);
            angular.module('myApp',['ngMessages']).directive('customValidation',function(){
                return{
                restrict:'A',
                require: 'ngModel',
                link:function (scope, element, attr, ctrl) {// 4th argument contain model information 
    
                function validationError(value) // you can use any function and parameter name 
                    {
                     if (value.length > 6) // if model length is greater then 6 it is valide state
                     {
                     ctrl.$setValidity('invalidshrt',true);
                     }
                     else
                     {
                     ctrl.$setValidity('invalidshrt',false) //if less then 6 is invalide
                     }
    
                     return value; //return to display  error 
                    }
                    ctrl.$parsers.push(validationError); //parsers change how view values will be saved in the model
                }
                };
            });
    
    <input type="text" name="fruitName" ng-model="data.fruitName" blacklist="Coconuts,Bananas,Pears" caseSensitive="true" required/>
    
    angular.module('crm.directives', []).
    directive('blacklist', [
        function () {
            return {
                restrict: 'A',
                require: 'ngModel',
                scope: {
                    'blacklist': '=',
                },
                link: function ($scope, $elem, $attrs, modelCtrl) {
    
                    var check = function (value) {
                        if (!$attrs.casesensitive) {
                            value = (value && value.toUpperCase) ? value.toUpperCase() : value;
    
                            $scope.blacklist = _.map($scope.blacklist, function (item) {
                                return (item.toUpperCase) ? item.toUpperCase() : item
                            })
                        }
    
                        return !_.isArray($scope.blacklist) || $scope.blacklist.indexOf(value) === -1;
                    }
    
                    //For DOM -> model validation
                    modelCtrl.$parsers.unshift(function (value) {
                        var valid = check(value);
                        modelCtrl.$setValidity('blacklist', valid);
    
                        return value;
                    });
                    //For model -> DOM validation
                    modelCtrl.$formatters.unshift(function (value) {
                        modelCtrl.$setValidity('blacklist', check(value));
                        return value;
                    });
                }
            };
        }
    ]);
    
    <input  type="text" name="field4" ng-model="field4"
            validity="eval"
            validity-eval="!(field1 && field2 && field3 && !field4)"
            validity-message-eval="This field is required">
    
    ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) {
      var value = modelValue || viewValue;
    
      // Lookup user by username
      return $http.get('/api/users/' + value).
         then(function resolved() {
           //username exists, this means validation fails
           return $q.reject('exists');
         }, function rejected() {
           //username does not exist, therefore this validation passes
           return true;
         });
    };
    
    app.directive('blacklist', function (){ 
       return {
          require: 'ngModel',
          link: function(scope, elem, attr, ngModel) {           
              ngModel.$validators.blacklist = function(modelValue, viewValue) {
                  var blacklist = attr.blacklist.split(',');
                  var value = modelValue || viewValue;
                  var valid = blacklist.indexOf(value) === -1;
                  return valid;
              });    
          }
       };
    });