AngularJS -- 表单验证
能够根据用户在表单中输入的内容给出实时视觉反馈是非常重要的。在人与人沟通的语境
中,表单验证给出来的反馈同获得正确输入同等重要。
AngularJS能够将HTML5表单验证功能同它自己的验证指令结合起来使用,
并且非常方便。
<form name="form" novalidate>
<label name="email">Your email</label>
<input type="email"
name="email"
ng-model="email" placeholder="Email Address" />
</form>
要使用表单验证,首先要确保表单像上面的例子一样有一个name属性。
所有输入字段都可以进行基本的验证,比如最大、最小长度等。这些功能是由新的
HTML5表单属性提供的。
如果想要屏蔽浏览器对表单的默认验证行为,可以在表单元素上添加
novalidate标记。
以下看一下可以在input元素上使用的所有验证选项。
-
1.必填项-》验证某个表单输入是否已填写,只要在输入字段元素上添加HTML5标记required即可:
<input type="text" required />
-
验证表单输入的文本长度是否大于某个最小值,在输入字段上使用AngularJS
指令ng-minleng= "{number}":<input type="text" ng-minlength="5" />
-
验证表单输入的文本长度是否小于或等于某个最大值,在输入字段上使用AngularJS指令
ng-maxlength="{number}":<input type="text" ng-maxlength="20" />
-
使用ng-pattern="/PATTERN/"来确保输入能够匹配指定的正则表达式:
<input type="text" ng-pattern="[a-zA-Z]" />
-
验证输入内容是否是电子邮件,只要像下面这样将input的类型设置为email
即可:<input type="email" name="email" ng-model="user.email" />
-
验证输入内容是否是数字,将input的类型设置为number:
<input type="number" name="age" ng-model="user.age" />
-
验证输入内容是否是URL,将input的类型设置为url:
<input type="url" name="homepage" ng-model="user.facebook_url" />
(注意,可以使用下面的格式访问这些属性。)
formName.inputFieldName.property
-
未修改的表单 这是一个布尔属性,用来判断用户是否修改了表单。如果未修改,值为true,如果修改过值为
false:formName.inputFieldName.$pristine
-
修改过的表单,只要用户修改过表单,无论输入是否通过验证,该值都返回
true:formName.inputFieldName.$dirty
-
合法的表单 这个布尔型的属性用来判断表单的内容是否合法。如果当前表单内容是合法的,下面属性的
值就是true:formName.inputFieldName.$valid
-
不合法的表单 这个布尔属性用来判断表单的内容是否不合法。如果当前表单内容是不合法的,下面属性的
值为true:formName.inputFieldName.$invalid
-
错误 这是AngularJS提供的另外一个非常有用的属性:$error对象。它包含当前表单的所有验证
内容,以及它们是否合法的信息。用下面的语法访问这个属性:formName.inputfieldName.$error
如果验证失败,这个属性的值为true;如果值为false,说明输入字段的值通过了验证。 -
一些有用的CSS样式 AngularJS处理表单时,会根据表单当前的状态添加一些CSS类(例如当前是合法的、未发生
变化的,等等),这些CSS类的命名和前面介绍的属性很相似。
它们包括:
.ng-pristine {}
.ng-dirty {}
.ng-valid {}
.ng-invalid {}
它们对应着表单输入字段的特定状态。
$parsers
当用户同控制器进行交互,并且ngModelController中的$setViewValue()
方法被调用时,$parsers数组中的函数会以流水线的形式被逐个调用。第一个$parse
被调用后,执行结果会传递给第二个$parse,以此类推。
这些函数可以对输入值进行转换,或者通过$setValidity()函数设置表单的合法性。
使用$parsers数组是实现自定义验证的途径之一。例如,假设我们想要确保输入值在某两个
数值之间,可以在$parsers数组中入一个新的函数,这个函数会验证链中被调用。
每个$parser返回的值都会被传入下一个$parser中。当不希望数据模型发生更新时返回undefined。
angular.module('myApp')
.directive('oneToTen', function() {
return {
require: '?ngModel',
link: function(scope, ele, attrs, ngModel) {
if (!ngModel) return;
ngModel.$parsers.unshift(
function(viewValue) {
var i = parseInt(viewValue);
if (i >= 0 && i < 10) {
ngModel.$setValidity('oneToTen', true);
return viewValue;
} else {
ngModel.$setValidity('oneToTen', false);
return undefined;
}
});
}
};
});
$formatters
比起单纯的验证目的,这些函数更常用来处理视图中的可视变化。例如,假设我们要对某个
值进行格式化。通过$formatters数组可以在这个值上执行过滤器:
angular.module('myApp')
.directive('oneToTen', function() {
return {
require: '?ngModel',
link: function(scope, ele, attrs, ngModel) {
if (!ngModel) return;
ngModel.$formatters.unshift(function(v) {
return $filter('number')(v);
});
}
};
});
- *不要忘记给输入字段添加name属性。给输入字段添加name属性非常重要:这块定了我们将验证信息
- 展示给用户如何引用表单输入字段。
同时,我们也设置了一些验证。验证要求name字段的最小长度是3个字符,最大长度是20个
字符(当长度大于等于21时输入会变为不合法)。最后,我们要求name字段是必填项。
通过使用这些属性,可以在表单未通过验证时控制展示或隐藏错误列表。用$dirty属性来确保用户未对输入内容进行修改时错误内容不会显示出来:
<divclass="row">
<div class="large-12 columns">
<label>Your name</label>
<input type="text"
placeholder="Name"
name="name"
ng-model="signup.name"
ng-minlength="3"
ng-maxlength="20" required />
<div class="error"
ng-show="signup_form.name.$dirty && signup_form.name.$invalid">
<small class="error"
ng-show="signup_form.name.$error.required">
Your name is required.
</small>
<small class="error"
ng-show="signup_form.name.$error.minlength">
Your name is required to be at least 3 characters
</small>
<small class="error"
ng-show="signup_form.name.$error.maxlength">
Your name cannot be longer than 20 characters
</small>
</div>
</div>
</div>
将整个过程分开来看,我们只是像以前一样在表单发生改变,且输入内容不会合法时才展示
错误内容。现在,我们会在特定的属性未通过验证时只展示对应的特定DOM元素。
<div class="row">
<div class="large-12 columns">
<label>Your email</label>
<input type="email"
placeholder="Email"
name="email"
ng-model="signup.email"
ng-minlength="3" ng-maxlength="20" required />
<div class="error"
ng-show="signup_form.email.$dirty && signup_form.email.$invalid">
<small class="error"
ng-show="signup_form.email.$error.required">
Your email is required.
</small>
<small class="error"
ng-show="signup_form.email.$error.minlength">
Your email is required to be at least 3 characters
</small>
<small class="error"
ng-show="signup_form.email.$error.email">
That is not a valid email. Please input a valid email.
</small>
<small class="error"
ng-show="signup_form.email.$error.maxlength">
Your email cannot be longer than 20 characters
</small>
</div>
</div>
</div>
现在整个表单都被包含进来了,我们来看一下电子邮件的输入字段。注意,我们将输入字段的TYPOE属性设置为email,
并且在$error.email上添加了验证错误信息。这个验证同事基于AngularJS 和 HTML5属实现。
在失焦后显示验证信息
如果想保留实时错误提示的体验,可以在用户从某个输入字段失去焦点后提示错误信息(例如用户已经不在某个特定的输入字段中时)。
为了实现这个效果,需要实现一个不是很复杂的指令,并向表单中添加一个新的变量。
我们需要使用的指令是ngFocus
,它是这样的:
app.directive('ngFocus', [function() {
var FOCUS_CLASS = "ng-focused";
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attrs, ctrl) {
ctrl.$focused = false;
element.bind('focus', function(evt) {
element.addClass(FOCUS_CLASS);
scope.$apply(function() {
ctrl.$focused = true;
});
}).bind('blur', function(evt) {
element.removeClass(FOCUS_CLASS);
scope.$apply(function() {
ctrl.$focused = false;
});
});
}
};
}]);
将ngFocus指令添加到input元素上就可以使用这个指令。
<input ng-class="{error: signup_form.name.$dirty && signup_form.name.$invalid}"
type="text"
placeholder="Name"
name="name"
ng-model="signup.name"
ng-minlength="3"
ng-maxlength="20" required ng-focus />
ngFocus指令给表单输入字段的blur和focus添加了对应的行为,添加了一个名为ng-focused的类,并将$focused的值设置为true
,接下来,可以根据表单是否具有焦点来展示独立的错误信息。
<div class="error"
ng-show="signup_form.name.$dirty && signup_form.name.$invalid && !signup_form.name.$focused">
衣可以在ngModel控制器中使用$isEmpty()方法来判断输入字段是否为空。当输入字段为空这个方法会返回true,反之
如果不为空则返回false。