angularjs 表单验证
进行表单验证时,第一步要确认form表单有name属性,eg. <form name='myForm'></form>
,最好屏蔽掉浏览器的默认表单验证:novalidate.
input上的所有验证选项:
1. 必填项
验证必填项,直接在input元素内加上:‘required’
<input type=text required>
2. 最小长度
直接在input元素上加:ng-minlength=’{number}’
<input type=text ng-minlength='5'/>
3. 最大长度
加:ng-maxlength=’{number}’
<input type=text ng-maxlength='15'/>
4. 模式匹配
加:ng-pattern=’/pattern/’ 来匹配正则表达式
<input type=text ng-pattern='[a-zA-Z]'/>
5. 电子邮件
将input的type值设置为email.
<input type=email name=email ng-model=user.email/>
6. 数字
经input的type值设置为number
<input type=number name=age ng-model=user.age/>
当验证电话号码时,只有11位数字,使用maxlength属性会与type=number相冲突,导致maxlength失效,解决办法是,将type=tel, maxlength=11, 再用正则/[0-9]/i.test(input.value)来判断输入是否为数字。
7. URL
将input的type值设置为url
<input type=url name=homepage ng-model=user.feedback_url/>
8. 自定义验证
稍后详细说明
访问表单属性
用下面格式访问部分表单属性方法:
表单名称.输入项名称.属性名
formName.inputFieldName.property
- 未修改过表单:formName.inputFieldName.$pristine
- 修改过表单:formName.inputFieldName.$dirty
- 合法表单:formName.inputFieldName.$valid
- 不合法表单:formName.inputFieldName.$invalid
- 错误表单:formName.inputFieldName.$error
Angular在处理这些信息时,会给表单增加上对应的CSS类。
自定义表单验证
当用户同控制器进行交互,并且ngModelController中的$setViewValue()方法被调用时,$parsers数组中的函数会以流水线的形式被逐个调用。第一个$parse被调用后,执行结果会传递给第二个$parse,以此类推。
使用$parsers数组是实现自定义验证的途径之一。例如,假设我们想要确保输入值在某两个数值之间,可以在$parsers数组中入栈一个新的函数,这个函数会在验证链中被调用。
eg:
link: function(scope, ele, attrs, ctrl) {
var url = attrs.ensureUnique;
ctrl.$parsers.push(function(val) {
if (!val || val.length === 0) {
return;
}
}
一般情况将自定义表单验证方法写入指令:
$setValidity:ctrl.$setValidity(errorName, boolean)
用来设置错误标志。
html:
<input phone-validate name='phone' type="tel" ng-model="phoneNumber" maxlength="11"/>
<span class='error' ng-show="myForm.phone.$dirty && myForm.phone.$invalid" style="color:red">
<span ng-show="myForm.phone.$error.phoneLength">必须为11位数字</span>
</span>
js:
app.directive('phoneValidate',function(){
return{
restrict:'A',
require:'ngModel',
link:function($scope,ele,attrs,ctrl){
$scope.$watch(attrs.ngModel,function(newValue){
if(!newValue) return;
if(ele.val().length==11&& /[0-9]/i.test(ele.val())){
/*
* $setValidity 用来设置$error错误标志
* $setValidity(errorName, true/false)
* 可以经过$error[errorName]来访问
* 并可以改变$invalid, $valid值
* */
ctrl.$setValidity('phoneLength',true)
}else{
ctrl.$setValidity('phoneLength',false);
}
})
}
}
})
失焦后验证
创建一个ngFocus指令,监控ctrl.$focused的变化。
html:
<input phone-validate type='tel' maxlength="11" name="phone" ng-model="user.phone" required class="form-control" placeholder="输入手机号" ng-focus/>
<span style="color:red" ng-show="myForm.phone.$dirty && myForm.phone.$invalid&& !myForm.phone.$focused ">
<span ng-show="myForm.phone.$error.phoneLength">必须为11位数字</span>
</span>
js:
app.directive('ngFocus',function(){
return{
restrict:'A',
require:'ngModel',
link:function(scope,elem,attr,ctrl){
ctrl.$focused=false;
elem.bind('focus',function(){
elem.addClass('focused');
scope.$apply(function(){ ctrl.$focused=true})
}).bind('blur',function(){
elem.removeClass('focused');
/*注意scope.$apply()方法的调用,目的是让视图里相关内容随时更新。*/
scope.$apply(function(){
ctrl.$focused=false;})
})
}
}
});
使用ngMessages插件:
<div class="error" ng-messages="myForm.name.$error" ng-messages-multiple>
<div ng-message="required"> sure you enter your name</div>
<div ng-message="minlength">Your name must be at least 3 characters</div>
<div ng-message="maxlength">Your name cannot be longer than 20 characters</div>
</div>
使用ngMessage插件时,若自定义验证指令,必须将错误消息自定义到ngModel中,而不是控制器中。
HTML:
<form name="signup_form" novalidate ng-submit="signupForm()" ng-controller="signupController"
ensure-unique="/api/checkUsername.json">
<label>
Your name
</label>
<input type="text" placeholder="Username" name="username" ng-model="signup.username"
ng-minlength=3 ng-maxlength=20 required />
<div class="error" ng-messages="signup_form.username.$error">
<div ng-message="required">
Make sure you enter your username
</div>
<div ng-message="checkingAvailability">
Checking...
</div>
<div ng-message="usernameAvailablity">
The username has already been taken. Please choose another
</div>
</div>
<button type="submit">
Submit
</button>
</form>
JS:
app.directive('ensureUnique', function($http) {
return {
require: 'ngModel',
link: function(scope, ele, attrs, ctrl) {
var url = attrs.ensureUnique;
ctrl.$parsers.push(function(val) {
if (!val || val.length === 0) {
return;
}
ngModel.$setValidity('checkingAvailability', true);
ngModel.$setValidity('usernameAvailablity', false);
$http({
method: 'GET',
url: url,
params: {
username: val
}
}).success(function() {
ngModel
.$setValidity('checkingAvailability', false);
ngModel
.$setValidity('usernameAvailablity', true);
})['catch'](function() {
ngModel
.$setValidity('checkingAvailability', false);
ngModel
.$setValidity('usernameAvailablity', false);
});
return val;
})
}
}
});
使用angular-validation.js插件
- 引入js文件
- 依赖注入app. eg.
var app=angular.module('app',['ui.router','ngCookies','validation']);
- 可以使用内置验证方法,或者自定义:
如下列:
angular.module('app').config(['$validationProvider', function($validationProvider) {
var expression = {
phone: /^1[\d]{10}$/,
password: function(value) {
var str = value + '';
return str.length > 5;
},
required: function(value) {
return !!value;
}
};
var defaultMsg = {
phone: {
success: '',
error: '必须是11位手机号'
},
password: {
success: '',
error: '长度至少6位'
},
required: {
success: '',
error: '不能为空!'
}
};
$validationProvider.setExpression(expression).setDefaultMsg(defaultMsg);
}]);
validataion.js API:
https://github.com/hueitan/angular-validation/blob/master/API.md