我有一个带有输入字段和验证设置的表单,通过添加required属性等.但对于某些领域,我需要做一些额外的验证.我如何"点击" FormController控件的验证?
自定义验证可能类似于"如果填写了这3个字段,则此字段是必需的,需要以特定方式进行格式化".
有一种方法,FormController.$setValidity但看起来不像公共API,所以我宁愿不使用它.创建一个自定义指令并使用NgModelController看起来像另一个选项,但基本上要求我为每个自定义验证规则创建一个指令,这是我不想要的.
实际上,将控制器中的字段标记为无效(同时保持FormController同步)可能是我在最简单的场景中完成工作所需要的,但我不知道该怎么做.
Ben*_*esh 365
编辑:添加了有关ngMessages(> = 1.3.X)的信息.
由于这是Google"Angular Form Validation"的最佳结果之一,目前,我想为来自那里的任何人添加另一个答案.
FormController中有一个方法.$ setValidity但看起来不像公共API,所以我宁愿不使用它.
这是"公开的",不用担心.用它.这就是它的用途.如果不打算使用它,Angular开发人员会将其私有化.
要进行自定义验证,如果您不想将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;
});
}
};
});
Run Code Online (Sandbox Code Playgroud)
以下是一些示例用法:
<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>
Run Code Online (Sandbox Code Playgroud)
注:在1.2.X它可能preferrable替换ng-if为ng-show上述
这是一个强制性的plunker链接
另外,我已经写了一些关于这个主题的博客文章更详细一些:
您现在可以使用ngMessages模块而不是ngShow来显示错误消息.它实际上可以处理任何事情,它不一定是一个错误信息,但这里是基础知识:
<script src="angular-messages.js"></script>ngMessages模块声明中的参考:
var app = angular.module('myApp', ['ngMessages']);
Run Code Online (Sandbox Code Playgroud)添加适当的标记:
<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>
Run Code Online (Sandbox Code Playgroud)在上面的标记中,ng-message="personForm.email.$error"基本上指定了ng-message子指令的上下文.然后 ng-message="required"和ng-message="email"指定有关这方面的属性来观看.最重要的是,他们还指定了一个检查它们的命令.它在列表中找到的第一个"truthy"获胜,它将显示该消息而不显示其他消息.
Pet*_* BD 92
Angular-UI的项目包含一个ui-validate指令,它可能会帮助你解决这个问题.它让你指定一个函数来调用来进行验证.
查看演示页面:http://angular-ui.github.com/,向下搜索Validate标题.
从演示页面:
<input ng-model="email" ui-validate='{blacklist : notBlackListed}'>
<span ng-show='form.email.$error.blacklist'>This e-mail is black-listed!</span>
Run Code Online (Sandbox Code Playgroud)
然后在你的控制器中:
function ValidateCtrl($scope) {
$scope.blackList = ['bad@domain.com','verybad@domain.com'];
$scope.notBlackListed = function(value) {
return $scope.blackList.indexOf(value) === -1;
};
}
Run Code Online (Sandbox Code Playgroud)
Mar*_* G. 46
您可以在验证方案中使用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>
Run Code Online (Sandbox Code Playgroud)
小智 28
您可以使用Angular-Validator.
示例:使用函数验证字段
<input type = "text"
name = "firstName"
ng-model = "person.firstName"
validator = "myCustomValidationFunction(form.firstName)">
Run Code Online (Sandbox Code Playgroud)
然后在你的控制器中你会有类似的东西
$scope.myCustomValidationFunction = function(firstName){
if ( firstName === "John") {
return true;
}
Run Code Online (Sandbox Code Playgroud)
你也可以这样做:
<input type = "text"
name = "firstName"
ng-model = "person.firstName"
validator = "'!(field1 && field2 && field3)'"
invalid-message = "'This field is required'">
Run Code Online (Sandbox Code Playgroud)
(其中field1 field2和field3是范围变量.您可能还想检查字段是否不等于空字符串)
如果该字段未通过,validator则该字段将被标记为无效,并且用户将无法提交该表单.
有关更多用例和示例,请参阅:https://github.com/turinggroup/angular-validator
免责声明:我是Angular-Validator的作者
Ben*_*ema 13
这是在表单中进行自定义通配符表达式验证的一种很酷的方法(来自:使用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>
Run Code Online (Sandbox Code Playgroud)
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);
});
}
};
}]);
Run Code Online (Sandbox Code Playgroud)
jsFiddle演示(支持表达式命名和多个表达式)
它类似于ui-validate,但你不需要范围特定的验证功能(这通常是有效的),并且当然你不需要这样的ui.utils.
小智 12
我最近创建了一个指令,允许基于表达式的角形式输入失效.可以使用任何有效的角度表达式,它使用对象表示法支持自定义验证密钥.用角度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);
});
}
}
};
}]);
Run Code Online (Sandbox Code Playgroud)
你可以像这样使用它:
<input ng-model="foo" invalid-if="{fooIsGreaterThanBar: 'foo > bar',
fooEqualsSomeFuncResult: 'foo == someFuncResult()'}/>
Run Code Online (Sandbox Code Playgroud)
或者只是传入一个表达式(它将被赋予默认的validationKey"invalidIf")
<input ng-model="foo" invalid-if="foo > bar"/>
Run Code Online (Sandbox Code Playgroud)
@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);
Run Code Online (Sandbox Code Playgroud)
更新:
具有相同功能的先前指令的改进和简化版本(一个而不是两个):
.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();
});
});
}
}
};
}])
Run Code Online (Sandbox Code Playgroud)
用法示例:
<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 />
Run Code Online (Sandbox Code Playgroud)
结果:相互依赖的测试表达式,其中在更改其他指令模型和当前模型时执行验证器。
测试表达式具有局部$model变量,应将其与其他变量进行比较。
先前:
我已经尝试通过添加额外的指令来改进@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();
});
});
}
};
}])
Run Code Online (Sandbox Code Playgroud)
示例如何使用它制作交叉验证的字段:
<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" />
Run Code Online (Sandbox Code Playgroud)
ensure-expression当变量ng-model或ensure-watch变量被更改时,执行来验证模型。
使用ngModelController $asyncValidatorsAPI处理异步验证,例如$http向后端发出请求。添加到对象的函数必须返回一个承诺,该承诺在有效时必须解决,在无效时必须拒绝。正在进行的异步验证通过 key 存储在ngModelController.$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;
});
};
Run Code Online (Sandbox Code Playgroud)
有关更多信息,请参阅
$validatorsAPI接受的答案使用$parsers和$formatters管道来添加自定义同步验证器。AngularJS 1.3+ 添加了$validatorsAPI,因此无需将验证器放入$parsers和$formatters管道中:
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;
});
}
};
});
Run Code Online (Sandbox Code Playgroud)
有关更多信息,请参阅AngularJS ngModelController API 参考 - $validators。
| 归档时间: |
|
| 查看次数: |
293369 次 |
| 最近记录: |