你将如何禁用或至少改变Angular如何验证type = email输入?
目前,如果你使用type = email,Angular本质上是双重验证..因为浏览器(在这种情况下为Chrome)验证了电子邮件,然后angular也是如此。不仅如此,但Chrome foo@bar
中的有效内容在Angularjs中无效。
我能找到的最好的是ng-pattern
,但ng-pattern
只是为输入类型添加 3rd 模式验证,而不是替换Angular的电子邮件验证。 HEH
有什么想法吗?
答案 0 :(得分:9)
注意:这是角度1.2.0-rc.3的示例。其他版本的情况可能会有所不同
像其他人一样,关闭角度默认输入验证有点复杂。您需要将自己的指令添加到input元素并处理其中的内容。 Sergey's answer是正确的,但如果你需要在元素上使用多个验证器并且不希望触发内置验证器,则会出现一些问题。
以下是验证添加了必需验证程序的电子邮件字段的示例。我在代码中添加了注释来解释发生了什么。
<input type="email" required>
angular.module('myValidations', [])
.directive('input', function () {
var self = {
// we use ?ngModel since not all input elements
// specify a model, e.g. type="submit"
require: '?ngModel'
// we need to set the priority higher than the base 0, otherwise the
// built in directive will still be applied
, priority: 1
// restrict this directive to elements
, restrict: 'E'
, link: function (scope, element, attrs, controller) {
// as stated above, a controller may not be present
if (controller) {
// in this case we only want to override the email validation
if (attrs.type === 'email') {
// clear this elements $parsers and $formatters
// NOTE: this will disable *ALL* previously set parsers
// and validators for this element. Beware!
controller.$parsers = [];
controller.$formatters = [];
// this function handles the actual validation
// see angular docs on how to write custom validators
// http://docs.angularjs.org/guide/forms
//
// in this example we are not going to actually validate an email
// properly since the regex can be damn long, so apply your own rules
var validateEmail = function (value) {
console.log("Validating as email", value);
if (controller.$isEmpty(value) || /@/.test(value)) {
controller.$setValidity('email', true);
return value;
} else {
controller.$setValidity('email', false);
return undefined;
}
};
// add the validator to the $parsers and $formatters
controller.$parsers.push(validateEmail);
controller.$formatters.push(validateEmail);
}
}
}
};
return self;
})
// define our required directive. It is a pretty standard
// validation directive with the exception of it's priority.
// a similar approach must be take with all validation directives
// you would want to use alongside our `input` directive
.directive('required', function () {
var self = {
// required should always be applied to a model element
require: 'ngModel'
, restrict: 'A'
// The priority needs to be higher than the `input` directive
// above, or it will be removed when that directive is run
, priority: 2
, link: function (scope, element, attrs, controller) {
var validateRequired = function (value) {
if (value) {
// it is valid
controller.$setValidity('required', true);
return value;
} else {
// it is invalid, return undefined (no model update)
controller.$setValidity('required', false);
return undefined;
}
};
controller.$parsers.push(validateRequired);
}
};
return self;
})
;
你有它。您现在可以控制type="email"
输入验证。请使用正确的正则表达式来测试电子邮件。
需要注意的一点是,在此示例中,validateEmail
在validateRequired
之前运行。如果您需要validateRequired
在任何其他验证之前运行,那么只需将其添加到$parsers
数组(使用unshift
而不是push
)。
答案 1 :(得分:8)
很简单。我不得不改变电子邮件正则表达式以匹配业务需求,所以我制定了这个指令,使电子邮件正则表达式可以自定义。它基本上用我的自定义覆盖原始验证器。你不必弄乱所有的$ parsers和$ formatters(除非我错过了什么)。所以我的指示就是这个......
module.directive('emailPattern', function(){
return {
require : 'ngModel',
link : function(scope, element, attrs, ngModel) {
var EMAIL_REGEX = new RegExp(attrs.emailPattern, "i");
ngModel.$validators["email"] = function (modelValue, viewValue) {
var value = modelValue || viewValue;
return ngModel.$isEmpty(value) || EMAIL_REGEX.test(value);
};
}
}
});
然后像这样使用它,提供您个人想要的任何电子邮件模式:
<input type="email" email-pattern=".+@.+\..+"/>
但如果您只想永久禁用它,那么您可以这样做。
module.directive('removeNgEmailValidation', function(){
return {
require : 'ngModel',
link : function(scope, element, attrs, ngModel) {
ngModel.$validators["email"] = function () {
return true;
};
}
}
});
然后像这样使用它......
<input type="email" remove-ng-email-validation>
答案 2 :(得分:7)
在HTML5上,您可以使用表单的属性novalidate
来禁用浏览器的验证:
<form novalidate>
<input type="email"/>
</form>
如果你想在angularjs中创建一个自定义验证器,你可以在这里找到一个很好的教程和示例:http://www.benlesh.com/2012/12/angular-js-custom-validation-via.html
答案 3 :(得分:4)
回应nfiniteloop,您不需要弄乱$parsers
或$formatters
来覆盖默认验证器。正如Angular 1.3 docs中所引用的那样,$ validators对象可以在ngModelController上访问。使用自定义指令,您可以根据需要编写尽可能多的不同电子邮件验证功能,并随时随地调用它们。
这是一个来自tuts: 8 Regular Expressions You Should Now的非常好的标准电子邮件格式正则表达式(可能与Angular的默认值,idk相同)。
var app = angular.module('myApp', []);
app.directive('customEmailValidate', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
var EMAIL_REGEXP = /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;
ctrl.$validators.email = function(modelValue, viewValue) {
if (ctrl.$isEmpty(modelValue)) {
// consider empty models to be valid
return true;
}
if (EMAIL_REGEXP.test(viewValue)) {
// it is valid
return true;
}
// it is invalid
return false;
};
}
};
});
以下是完全删除验证的内容:
var app = angular.module('myApp', []);
app.directive('noValidation', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
ctrl.$validators.email = function(modelValue, viewValue) {
// everything is valid
return true;
};
}
};
});
要在您的标记中使用:
<!-- 'test@example.com' is valid, '@efe@eh.c' is invalid -->
<input type="email" custom-email-validate>
<!-- both 'test@example.com' and '@efe@eh.c' are valid -->
<input type="email" no-validation>
答案 4 :(得分:2)
在我的项目中,我做了类似的事情(自定义指令会删除所有其他验证,包括由angularjs安装的验证):
angular.module('my-project').directive('validEmail', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl){
var validator = function(value){
if (value == '' || typeof value == 'undefined') {
ctrl.$setValidity('validEmail', true);
} else {
ctrl.$setValidity('validEmail', /your-regexp-here/.test(value));
}
return value;
};
// replace all other validators!
ctrl.$parsers = [validator];
ctrl.$formatters = [validator];
}
}
});
如何使用它(注意novalidate
,需要关闭浏览器验证):
<form novalidate>
<input type="email" model="email" class="form-control" valid-email>