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

时间:2021-09-26 08:11:47

I have a form with input fields and validation setup by adding the required attributes and such. But for some fields I need to do some extra validation. How would I "tap in" to the validation that FormController controls?

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

Custom validation could be something like "if these 3 fields are filled in, then this field is required and needs to be formatted in a particular way".

自定义验证可以是“如果这3个字段被填充,那么这个字段是必需的,需要以特定的方式进行格式化”。

There's a method in FormController.$setValidity but that doesn't look like a public API so I rather not use it. Creating a custom directive and using NgModelController looks like another option, but would basically require me to create a directive for each custom validation rule, which I do not want.

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

Actually, marking a field from the controller as invalid (while also keeping FormController in sync) might be the thing that I need in the simplest scenario to get the job done, but I don't know how to do that.

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

12 个解决方案

#1


349  

Edit: added information about ngMessages (>= 1.3.X) below.

编辑:添加关于ngMessages的信息(>= 1.3.X)。

Standard form validation messages (1.0.X and above)

Since this is one of the top results if you Google "Angular Form Validation", currently, I want to add another answer to this for anyone coming in from there.

由于这是谷歌“角形验证”的最高结果之一,目前,我想为从这里进来的任何人添加另一个答案。

There's a method in FormController.$setValidity but that doesn't look like a public API so I rather not use it.

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

It's "public", no worries. Use it. That's what it's for. If it weren't meant to be used, the Angular devs would have privatized it in a closure.

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

To do custom validation, if you don't want to use Angular-UI as the other answer suggested, you can simply roll your own validation directive.

要进行自定义验证,如果您不想使用Angular-UI作为其他答案,您可以简单地滚动自己的验证指令。

app.directive('blacklist', function (){ 
   return {
      require: 'ngModel',
      link: function(scope, elem, attr, ngModel) {
          var blacklist = attr.blacklist.split(',');

          //For DOM -> model validation
          ngModel.$parsers.unshift(function(value) {
             var valid = blacklist.indexOf(value) === -1;
             ngModel.$setValidity('blacklist', valid);
             return valid ? value : undefined;
          });

          //For model -> DOM validation
          ngModel.$formatters.unshift(function(value) {
             ngModel.$setValidity('blacklist', blacklist.indexOf(value) === -1);
             return value;
          });
      }
   };
});

And here's some example usage:

这里有一些例子用法:

<form name="myForm" ng-submit="doSomething()">
   <input type="text" name="fruitName" ng-model="data.fruitName" blacklist="coconuts,bananas,pears" required/>
   <span ng-show="myForm.fruitName.$error.blacklist">
      The phrase "{{data.fruitName}}" is blacklisted</span>
   <span ng-show="myForm.fruitName.$error.required">required</span>
   <button type="submit" ng-disabled="myForm.$invalid">Submit</button>
</form>

Note: in 1.2.X it's probably preferrable to substitute ng-if for ng-show above

注意:在1.2。可能更倾向于用ng-if来代替上面提到的ng-show

Here is an obligatory plunker link

这是一个必须的柱塞环

Also, I've written a few blog entries about just this subject that goes into a little more detail:

此外,我还写了一些关于这个主题的博客文章,其中有更多的细节:

Angular Form Validation

角表单验证

Custom Validation Directives

自定义验证指令

Edit: using ngMessages in 1.3.X

You can now use the ngMessages module instead of ngShow to show your error messages. It will actually work with anything, it doesn't have to be an error message, but here's the basics:

现在可以使用ngmessage模块而不是ngShow来显示错误消息。它实际上可以处理任何事情,它不一定是一条错误消息,但是这里有一些基本的东西:

  1. Include <script src="angular-messages.js"></script>
  2. 包括< script src = " angular-messages.js " > < /脚本>
  3. Reference ngMessages in your module declaration:

    在模块声明中引用ngmessage:

    var app = angular.module('myApp', ['ngMessages']);
    
  4. Add the appropriate markup:

    添加适当的标记:

    <form name="personForm">
      <input type="email" name="email" ng-model="person.email" required/>
    
      <div ng-messages="personForm.email.$error">
        <div ng-message="required">required</div>
        <div ng-message="email">invalid email</div>
      </div>
    </form>
    

In the above markup, ng-message="personForm.email.$error" basically specifies a context for the ng-message child directives. Then ng-message="required" and ng-message="email" specify properties on that context to watch. Most importantly, they also specify an order to check them in. The first one it finds in the list that is "truthy" wins, and it will show that message and none of the others.

在上面的标记中,ng-message=“personForm.email”。$error“主要指定ng-message子指令的上下文。然后,ng-message="required"和ng-message="email"指定要监视的上下文上的属性。最重要的是,它们还指定一个订单来检入它们。它在列表中找到的第一个是“truthy”的胜利,它将显示这个消息,而不是其他的消息。

And a plunker for the ngMessages example

以及ngMessages示例的插入器

#2


91  

Angular-UI's project includes a ui-validate directive, which will probably help you with this. It let's you specify a function to call to do the validation.

Angular-UI的项目包含一个ui-validate指令,它可能会帮助您实现这一点。它让你指定一个函数来调用验证。

Have a look at the demo page: http://angular-ui.github.com/, search down to the Validate heading.

查看演示页面:http://angular-ui.github.com/,搜索到验证标题。

From the demo page:

从演示页面:

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

then in your controller:

然后在你的控制器:

function ValidateCtrl($scope) {
  $scope.blackList = ['bad@domain.com','verybad@domain.com'];
  $scope.notBlackListed = function(value) {
    return $scope.blackList.indexOf(value) === -1;
  };
}

#3


43  

You can use ng-required for your validation scenario ("if these 3 fields are filled in, then this field is required":

您可以在您的验证场景中使用ng-required(“如果填入这3个字段,则需要这个字段”):

<div ng-app>
    <input type="text" ng-model="field1" placeholder="Field1">
    <input type="text" ng-model="field2" placeholder="Field2">
    <input type="text" ng-model="field3" placeholder="Field3">
    <input type="text" ng-model="dependentField" placeholder="Custom validation"
        ng-required="field1 && field2 && field3">
</div>

#4


27  

You can use Angular-Validator.

您可以使用Angular-Validator。

Example: using a function to validate a field

示例:使用函数验证字段

<input  type = "text"
    name = "firstName"
    ng-model = "person.firstName"
    validator = "myCustomValidationFunction(form.firstName)">

Then in your controller you would have something like

在你的控制器中你会有类似的东西

$scope.myCustomValidationFunction = function(firstName){ 
   if ( firstName === "John") {
       return true;
    }

You can also do something like this:

你也可以这样做:

<input  type = "text"
        name = "firstName"
        ng-model = "person.firstName"
        validator = "'!(field1 && field2 && field3)'"
        invalid-message = "'This field is required'">

(where field1 field2, and field3 are scope variables. You might also want to check if the fields do not equal the empty string)

(其中field1 field2和field3是范围变量。您可能还想检查字段是否不等于空字符串)

If the field does not pass the validator then the field will be marked as invalid and the user will not be able to submit the form.

如果该字段没有通过验证器,那么该字段将被标记为无效,用户将无法提交表单。

For more use cases and examples see: https://github.com/turinggroup/angular-validator

有关更多的用例和示例,请参见:https://github.com/turinggroup/angular-validator

Disclaimer: I am the author of Angular-Validator

免责声明:我是angular验证器的作者

#5


12  

Here's a cool way to do custom wildcard expression validations in a form (from: Advanced form validation with AngularJS and filters):

这里有一种很酷的方式来进行表单中的自定义通配符表达式验证(来自:使用AngularJS和过滤器的高级表单验证):

<form novalidate="">  
   <input type="text" id="name" name="name" ng-model="newPerson.name"
      ensure-expression="(persons | filter:{name: newPerson.name}:true).length !== 1">
   <!-- or in your case:-->
   <input type="text" id="fruitName" name="fruitName" ng-model="data.fruitName"
      ensure-expression="(blacklist | filter:{fruitName: data.fruitName}:true).length !== 1">
</form>
app.directive('ensureExpression', ['$http', '$parse', function($http, $parse) {
    return {
        require: 'ngModel',
        link: function(scope, ele, attrs, ngModelController) {
            scope.$watch(attrs.ngModel, function(value) {
                var booleanResult = $parse(attrs.ensureExpression)(scope);
                ngModelController.$setValidity('expression', booleanResult);
            });
        }
    };
}]);

jsFiddle demo (supports expression naming and multiple expressions)

jsFiddle demo(支持表达式命名和多个表达式)

It's similar to ui-validate, but you don't need a scope specific validation function (this works generically) and ofcourse you don't need ui.utils this way.

它类似于ui-validate,但是您不需要特定范围的验证函数(这是通用的),当然也不需要ui。跑龙套。

#6


11  

I recently created a directive to allow for expression-based invalidation of angular form inputs. Any valid angular expression can be used, and it supports custom validation keys using object notation. Tested with angular v1.3.8

我最近创建了一个指令,允许基于表达式的角度形式输入失效。可以使用任何有效的角度表达式,并且它支持使用对象表示法的自定义验证键。测试角v1.3.8

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

You can use it like this:

你可以这样使用:

<input ng-model="foo" invalid-if="{fooIsGreaterThanBar: 'foo > bar',
                                   fooEqualsSomeFuncResult: 'foo == someFuncResult()'}/>

Or by just passing in an expression (it will be given the default validationKey of "invalidIf")

或者只是传递一个表达式(它将被赋予“invalidIf”的默认验证键)

<input ng-model="foo" invalid-if="foo > bar"/>

#7


4  

@synergetic I think @blesh suppose to put function validate as below

@synergetic我认为@blesh应该把函数validate放在下面

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

#8


4  

Update:

更新:

Improved and simplified version of previous directive (one instead of two) with same functionality:

改进和简化了以前的指令(一个而不是两个)的版本,具有相同的功能:

.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();
                    });
                });
            }
        }
    };
}])

Example usage:

使用示例:

<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 />

Result: Mutually dependent test expressions where validators are executed on change of other's directive model and current model.

结果:在其他的指令模型和当前模型的变化中执行验证器的相互依赖的测试表达式。

Test expression has local $model variable which you should use to compare it to other variables.

Test expression有本地$model变量,您应该使用它来与其他变量进行比较。

Previously:

以前:

I've made an attempt to improve @Plantface code by adding extra directive. This extra directive very useful if our expression needs to be executed when changes are made in more than one ngModel variables.

我尝试通过添加额外指令来改进@Plantface代码。如果我们的表达式需要在多个ngModel变量中进行更改时,这个额外的指令非常有用。

.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();
                });
            });
        }
    };
}])

Example how to use it to make cross validated fields:

示例如何使用它来创建交叉验证字段:

<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" />

ensure-expression is executed to validate model when ng-model or any of ensure-watch variables is changed.

当ng-model或任何ensure-watch变量被更改时,执行ensure-expression来验证模型。

#9


3  

In AngularJS the best place to define Custom Validation is Cutsom directive. AngularJS provide a ngMessages module.

在AngularJS中,定义自定义验证的最佳位置是Cutsom指令。AngularJS提供一个ngmessage模块。

ngMessages is a directive that is designed to show and hide messages based on the state of a key/value object that it listens on. The directive itself complements error message reporting with the ngModel $error object (which stores a key/value state of validation errors).

ngMessages是一个指令,它的设计目的是显示和隐藏基于它监听的键/值对象状态的消息。该指令本身补充了错误消息报告与ngModel $error对象(该对象存储验证错误的键/值状态)。

For custom form validation One should use ngMessages Modules with custom directive.Here i have a simple validation which will check if number length is less then 6 display an error on screen

对于自定义表单验证,应该使用带有自定义指令的ngmessage模块。这里我有一个简单的验证,它将检查数字长度是否小于6显示屏幕上的错误。

 <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>

Here is how to create custom validation directive

下面是如何创建自定义验证指令

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

$setValidity is inbuilt function to set model state to valid/invalid

$setValidity是内建函数,用于将模型状态设置为有效/无效

#10


1  

I extended @Ben Lesh's answer with an ability to specify whether the validation is case sensitive or not (default)

我扩展了@Ben Lesh的答案,可以指定验证是否区分大小写(默认)

use:

使用:

<input type="text" name="fruitName" ng-model="data.fruitName" blacklist="Coconuts,Bananas,Pears" caseSensitive="true" required/>

code:

代码:

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

#11


1  

Custom Validations that call a Server

Use the ngModelController $asyncValidators API which handles asynchronous validation, such as making an $http request to the backend. Functions added to the object must return a promise that must be resolved when valid or rejected when invalid. In-progress async validations are stored by key in ngModelController.$pending. For more information, see AngularJS Developer Guide - Forms (Custom Validation).

使用ngModelController $asyncValidators API处理异步验证,例如向后端发出$http请求。添加到对象的函数必须返回一个承诺,该承诺在有效时必须得到解决,在无效时必须被拒绝。正在进行的异步验证由ngModelController中的key存储。$pending。有关更多信息,请参阅AngularJS开发人员指南——表单(自定义验证)。

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

For more information, see

有关更多信息,请参见

#12


0  

Some great examples and libs presented in this thread, but they didn't quite have what I was looking for. My approach: angular-validity -- a promise based validation lib for asynchronous validation, with optional Bootstrap styling baked-in.

在这个线程中出现了一些很好的例子和lib,但是它们并没有我想要的那样。我的方法:angular-validity——一个基于承诺的异步验证库,具有可选的引导样式。

An angular-validity solution for the OP's use case might look something like this:

OP的用例的angular-有效性解决方案可能是这样的:

<input  type="text" name="field4" ng-model="field4"
        validity="eval"
        validity-eval="!(field1 && field2 && field3 && !field4)"
        validity-message-eval="This field is required">

Here's a Fiddle, if you want to take it for a spin. The lib is available on GitHub, has detailed documentation, and plenty of live demos.

这是一把小提琴,如果你想要旋转的话。lib在GitHub上可用,有详细的文档和大量的现场演示。

#1


349  

Edit: added information about ngMessages (>= 1.3.X) below.

编辑:添加关于ngMessages的信息(>= 1.3.X)。

Standard form validation messages (1.0.X and above)

Since this is one of the top results if you Google "Angular Form Validation", currently, I want to add another answer to this for anyone coming in from there.

由于这是谷歌“角形验证”的最高结果之一,目前,我想为从这里进来的任何人添加另一个答案。

There's a method in FormController.$setValidity but that doesn't look like a public API so I rather not use it.

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

It's "public", no worries. Use it. That's what it's for. If it weren't meant to be used, the Angular devs would have privatized it in a closure.

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

To do custom validation, if you don't want to use Angular-UI as the other answer suggested, you can simply roll your own validation directive.

要进行自定义验证,如果您不想使用Angular-UI作为其他答案,您可以简单地滚动自己的验证指令。

app.directive('blacklist', function (){ 
   return {
      require: 'ngModel',
      link: function(scope, elem, attr, ngModel) {
          var blacklist = attr.blacklist.split(',');

          //For DOM -> model validation
          ngModel.$parsers.unshift(function(value) {
             var valid = blacklist.indexOf(value) === -1;
             ngModel.$setValidity('blacklist', valid);
             return valid ? value : undefined;
          });

          //For model -> DOM validation
          ngModel.$formatters.unshift(function(value) {
             ngModel.$setValidity('blacklist', blacklist.indexOf(value) === -1);
             return value;
          });
      }
   };
});

And here's some example usage:

这里有一些例子用法:

<form name="myForm" ng-submit="doSomething()">
   <input type="text" name="fruitName" ng-model="data.fruitName" blacklist="coconuts,bananas,pears" required/>
   <span ng-show="myForm.fruitName.$error.blacklist">
      The phrase "{{data.fruitName}}" is blacklisted</span>
   <span ng-show="myForm.fruitName.$error.required">required</span>
   <button type="submit" ng-disabled="myForm.$invalid">Submit</button>
</form>

Note: in 1.2.X it's probably preferrable to substitute ng-if for ng-show above

注意:在1.2。可能更倾向于用ng-if来代替上面提到的ng-show

Here is an obligatory plunker link

这是一个必须的柱塞环

Also, I've written a few blog entries about just this subject that goes into a little more detail:

此外,我还写了一些关于这个主题的博客文章,其中有更多的细节:

Angular Form Validation

角表单验证

Custom Validation Directives

自定义验证指令

Edit: using ngMessages in 1.3.X

You can now use the ngMessages module instead of ngShow to show your error messages. It will actually work with anything, it doesn't have to be an error message, but here's the basics:

现在可以使用ngmessage模块而不是ngShow来显示错误消息。它实际上可以处理任何事情,它不一定是一条错误消息,但是这里有一些基本的东西:

  1. Include <script src="angular-messages.js"></script>
  2. 包括< script src = " angular-messages.js " > < /脚本>
  3. Reference ngMessages in your module declaration:

    在模块声明中引用ngmessage:

    var app = angular.module('myApp', ['ngMessages']);
    
  4. Add the appropriate markup:

    添加适当的标记:

    <form name="personForm">
      <input type="email" name="email" ng-model="person.email" required/>
    
      <div ng-messages="personForm.email.$error">
        <div ng-message="required">required</div>
        <div ng-message="email">invalid email</div>
      </div>
    </form>
    

In the above markup, ng-message="personForm.email.$error" basically specifies a context for the ng-message child directives. Then ng-message="required" and ng-message="email" specify properties on that context to watch. Most importantly, they also specify an order to check them in. The first one it finds in the list that is "truthy" wins, and it will show that message and none of the others.

在上面的标记中,ng-message=“personForm.email”。$error“主要指定ng-message子指令的上下文。然后,ng-message="required"和ng-message="email"指定要监视的上下文上的属性。最重要的是,它们还指定一个订单来检入它们。它在列表中找到的第一个是“truthy”的胜利,它将显示这个消息,而不是其他的消息。

And a plunker for the ngMessages example

以及ngMessages示例的插入器

#2


91  

Angular-UI's project includes a ui-validate directive, which will probably help you with this. It let's you specify a function to call to do the validation.

Angular-UI的项目包含一个ui-validate指令,它可能会帮助您实现这一点。它让你指定一个函数来调用验证。

Have a look at the demo page: http://angular-ui.github.com/, search down to the Validate heading.

查看演示页面:http://angular-ui.github.com/,搜索到验证标题。

From the demo page:

从演示页面:

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

then in your controller:

然后在你的控制器:

function ValidateCtrl($scope) {
  $scope.blackList = ['bad@domain.com','verybad@domain.com'];
  $scope.notBlackListed = function(value) {
    return $scope.blackList.indexOf(value) === -1;
  };
}

#3


43  

You can use ng-required for your validation scenario ("if these 3 fields are filled in, then this field is required":

您可以在您的验证场景中使用ng-required(“如果填入这3个字段,则需要这个字段”):

<div ng-app>
    <input type="text" ng-model="field1" placeholder="Field1">
    <input type="text" ng-model="field2" placeholder="Field2">
    <input type="text" ng-model="field3" placeholder="Field3">
    <input type="text" ng-model="dependentField" placeholder="Custom validation"
        ng-required="field1 && field2 && field3">
</div>

#4


27  

You can use Angular-Validator.

您可以使用Angular-Validator。

Example: using a function to validate a field

示例:使用函数验证字段

<input  type = "text"
    name = "firstName"
    ng-model = "person.firstName"
    validator = "myCustomValidationFunction(form.firstName)">

Then in your controller you would have something like

在你的控制器中你会有类似的东西

$scope.myCustomValidationFunction = function(firstName){ 
   if ( firstName === "John") {
       return true;
    }

You can also do something like this:

你也可以这样做:

<input  type = "text"
        name = "firstName"
        ng-model = "person.firstName"
        validator = "'!(field1 && field2 && field3)'"
        invalid-message = "'This field is required'">

(where field1 field2, and field3 are scope variables. You might also want to check if the fields do not equal the empty string)

(其中field1 field2和field3是范围变量。您可能还想检查字段是否不等于空字符串)

If the field does not pass the validator then the field will be marked as invalid and the user will not be able to submit the form.

如果该字段没有通过验证器,那么该字段将被标记为无效,用户将无法提交表单。

For more use cases and examples see: https://github.com/turinggroup/angular-validator

有关更多的用例和示例,请参见:https://github.com/turinggroup/angular-validator

Disclaimer: I am the author of Angular-Validator

免责声明:我是angular验证器的作者

#5


12  

Here's a cool way to do custom wildcard expression validations in a form (from: Advanced form validation with AngularJS and filters):

这里有一种很酷的方式来进行表单中的自定义通配符表达式验证(来自:使用AngularJS和过滤器的高级表单验证):

<form novalidate="">  
   <input type="text" id="name" name="name" ng-model="newPerson.name"
      ensure-expression="(persons | filter:{name: newPerson.name}:true).length !== 1">
   <!-- or in your case:-->
   <input type="text" id="fruitName" name="fruitName" ng-model="data.fruitName"
      ensure-expression="(blacklist | filter:{fruitName: data.fruitName}:true).length !== 1">
</form>
app.directive('ensureExpression', ['$http', '$parse', function($http, $parse) {
    return {
        require: 'ngModel',
        link: function(scope, ele, attrs, ngModelController) {
            scope.$watch(attrs.ngModel, function(value) {
                var booleanResult = $parse(attrs.ensureExpression)(scope);
                ngModelController.$setValidity('expression', booleanResult);
            });
        }
    };
}]);

jsFiddle demo (supports expression naming and multiple expressions)

jsFiddle demo(支持表达式命名和多个表达式)

It's similar to ui-validate, but you don't need a scope specific validation function (this works generically) and ofcourse you don't need ui.utils this way.

它类似于ui-validate,但是您不需要特定范围的验证函数(这是通用的),当然也不需要ui。跑龙套。

#6


11  

I recently created a directive to allow for expression-based invalidation of angular form inputs. Any valid angular expression can be used, and it supports custom validation keys using object notation. Tested with angular v1.3.8

我最近创建了一个指令,允许基于表达式的角度形式输入失效。可以使用任何有效的角度表达式,并且它支持使用对象表示法的自定义验证键。测试角v1.3.8

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

You can use it like this:

你可以这样使用:

<input ng-model="foo" invalid-if="{fooIsGreaterThanBar: 'foo > bar',
                                   fooEqualsSomeFuncResult: 'foo == someFuncResult()'}/>

Or by just passing in an expression (it will be given the default validationKey of "invalidIf")

或者只是传递一个表达式(它将被赋予“invalidIf”的默认验证键)

<input ng-model="foo" invalid-if="foo > bar"/>

#7


4  

@synergetic I think @blesh suppose to put function validate as below

@synergetic我认为@blesh应该把函数validate放在下面

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

#8


4  

Update:

更新:

Improved and simplified version of previous directive (one instead of two) with same functionality:

改进和简化了以前的指令(一个而不是两个)的版本,具有相同的功能:

.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();
                    });
                });
            }
        }
    };
}])

Example usage:

使用示例:

<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 />

Result: Mutually dependent test expressions where validators are executed on change of other's directive model and current model.

结果:在其他的指令模型和当前模型的变化中执行验证器的相互依赖的测试表达式。

Test expression has local $model variable which you should use to compare it to other variables.

Test expression有本地$model变量,您应该使用它来与其他变量进行比较。

Previously:

以前:

I've made an attempt to improve @Plantface code by adding extra directive. This extra directive very useful if our expression needs to be executed when changes are made in more than one ngModel variables.

我尝试通过添加额外指令来改进@Plantface代码。如果我们的表达式需要在多个ngModel变量中进行更改时,这个额外的指令非常有用。

.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();
                });
            });
        }
    };
}])

Example how to use it to make cross validated fields:

示例如何使用它来创建交叉验证字段:

<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" />

ensure-expression is executed to validate model when ng-model or any of ensure-watch variables is changed.

当ng-model或任何ensure-watch变量被更改时,执行ensure-expression来验证模型。

#9


3  

In AngularJS the best place to define Custom Validation is Cutsom directive. AngularJS provide a ngMessages module.

在AngularJS中,定义自定义验证的最佳位置是Cutsom指令。AngularJS提供一个ngmessage模块。

ngMessages is a directive that is designed to show and hide messages based on the state of a key/value object that it listens on. The directive itself complements error message reporting with the ngModel $error object (which stores a key/value state of validation errors).

ngMessages是一个指令,它的设计目的是显示和隐藏基于它监听的键/值对象状态的消息。该指令本身补充了错误消息报告与ngModel $error对象(该对象存储验证错误的键/值状态)。

For custom form validation One should use ngMessages Modules with custom directive.Here i have a simple validation which will check if number length is less then 6 display an error on screen

对于自定义表单验证,应该使用带有自定义指令的ngmessage模块。这里我有一个简单的验证,它将检查数字长度是否小于6显示屏幕上的错误。

 <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>

Here is how to create custom validation directive

下面是如何创建自定义验证指令

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

$setValidity is inbuilt function to set model state to valid/invalid

$setValidity是内建函数,用于将模型状态设置为有效/无效

#10


1  

I extended @Ben Lesh's answer with an ability to specify whether the validation is case sensitive or not (default)

我扩展了@Ben Lesh的答案,可以指定验证是否区分大小写(默认)

use:

使用:

<input type="text" name="fruitName" ng-model="data.fruitName" blacklist="Coconuts,Bananas,Pears" caseSensitive="true" required/>

code:

代码:

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

#11


1  

Custom Validations that call a Server

Use the ngModelController $asyncValidators API which handles asynchronous validation, such as making an $http request to the backend. Functions added to the object must return a promise that must be resolved when valid or rejected when invalid. In-progress async validations are stored by key in ngModelController.$pending. For more information, see AngularJS Developer Guide - Forms (Custom Validation).

使用ngModelController $asyncValidators API处理异步验证,例如向后端发出$http请求。添加到对象的函数必须返回一个承诺,该承诺在有效时必须得到解决,在无效时必须被拒绝。正在进行的异步验证由ngModelController中的key存储。$pending。有关更多信息,请参阅AngularJS开发人员指南——表单(自定义验证)。

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

For more information, see

有关更多信息,请参见

#12


0  

Some great examples and libs presented in this thread, but they didn't quite have what I was looking for. My approach: angular-validity -- a promise based validation lib for asynchronous validation, with optional Bootstrap styling baked-in.

在这个线程中出现了一些很好的例子和lib,但是它们并没有我想要的那样。我的方法:angular-validity——一个基于承诺的异步验证库,具有可选的引导样式。

An angular-validity solution for the OP's use case might look something like this:

OP的用例的angular-有效性解决方案可能是这样的:

<input  type="text" name="field4" ng-model="field4"
        validity="eval"
        validity-eval="!(field1 && field2 && field3 && !field4)"
        validity-message-eval="This field is required">

Here's a Fiddle, if you want to take it for a spin. The lib is available on GitHub, has detailed documentation, and plenty of live demos.

这是一把小提琴,如果你想要旋转的话。lib在GitHub上可用,有详细的文档和大量的现场演示。