AngularJS 表单提交后显示验证信息与失焦后显示验证信息
虽然说AngularJS的实时表单验证非常有用,非常高效方便,但是当用户还没有完成输入时便弹出一个错误提示,这种体验是非常糟糕的。
正常的表单验证逻辑应该是在用户提交表单后或完成当前字段中的输入后,再提示验证信息,这样才是用户友好的。下面就来看看如何实现
- 在表单提交后显示验证信息
- 在失焦后显示验证信息
在表单提交后显示验证信息
在用户试图提交表单时,你可以在作用域中捕获一个submitted值,然后对表单内容进行验证并显示错误信息。
下面通过一个简单的例子来说明,只在用户提交表单时才显示错误信息。在ng-show 指令中添加对submitted(判断表单是否提交)的检查,仅有当submitted的值为true(即表示表单已提交)同时该表单元素是处于$invalid状态的时候,错误信息就会显示出来
HTML代码
<form name="registerForm" class="registerForm" novalidate ng-submit="register(user)"> <div class="title">欢迎注册,和我们一起甜蜜生活</div> <div class="form-group " ng-class="registerForm.username.$invalid ? '' : 'has-success'"> <div class="input-group"> <div class="input-group-addon"><span class=" iconfont icon-register icon-phone"></span></div> <input type="text" name="username" class="form-control" placeholder="请输入手机号码" ng-model="user.username" maxlength="11" required ng-pattern="/1[3|5|7|8|][0-9]{9}/"/> </div> <div class="form-error" ng-show="registerForm.username.$invalid && submitted "> <span ng-show="registerForm.username.$error.required">手机号不能为空</span> <span ng-show="registerForm.username.$error.pattern">请输入正确的手机号码</span> </div> </div> <input type="submit" value="注册" class="btn btn-register btn-tianmi"/> {{result}} </form>
Controller代码
$scope.submitted = false $scope.register = function (user) { //表单正常提交 if($scope.registerForm.$valid){ //正常提交表单 } else{ $scope.submitted = true; } };
通过上面的方法,便可以实现用户在有非法输入的情况下提交表单,将显示错误信息
在失焦后显示验证信息
要想保留用户在输入某个字段失焦后提示错误信息,需要实现一个ngFocus的指令,并在表单中添加该指令
ngFocus指令代码
.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 () { element.removeClass(FOCUS_CLASS); scope.$apply(function(){ ctrl.$focused = false; }) }) } } })
接下来将ngFocus指令添加到input的元素上就可以使用该指令,依然用上面的表单例子
<form name="registerForm" class="registerForm" novalidate ng-submit="register(user)"> <div class="title">欢迎注册,和我们一起甜蜜生活</div> <div class="form-group " ng-class="registerForm.username.$invalid ? '' : 'has-success'"> <div class="input-group"> <div class="input-group-addon"><span class=" iconfont icon-register icon-phone"></span></div> <input type="text" name="username" class="form-control" placeholder="请输入手机号码" ng-model="user.username" maxlength="11" required ng-pattern="/1[3|5|7|8|][0-9]{9}/" ng-focus/> </div> <div class="form-error" ng-show="registerForm.username.$invalid && !registerForm.username.$focused "> <span ng-show="registerForm.username.$error.required">手机号不能为空</span> <span ng-show="registerForm.username.$error.pattern">请输入正确的手机号码</span> </div> </div> <input type="submit" value="注册" class="btn btn-register btn-tianmi"/> {{result}} </form>
ngFocus指令给表单输入字段的blur和focus添加了相应的行为,添加了一个名为ng-focused的类,并将$focused的值设置为true。这样就可以通过判断表单是否具有焦点来显示错误信息
<div class="form-error" ng-show="registerForm.username.$invalid && !registerForm.username.$focused "> <span ng-show="registerForm.username.$error.required">手机号不能为空</span> <span ng-show="registerForm.username.$error.pattern">请输入正确的手机号码</span> </div>
当然了,在正常的情况下,我们一般是使用失焦后验证+表单提交后验证两种方式相结合的形式来进行表单验证。下面就通过一个完整的用户注册例子来显示如果实现这种验证方式。
HTMl代码
<form name="registerForm" class="registerForm" novalidate ng-submit="register(user)"> <div class="title">欢迎注册,和我们一起甜蜜生活</div> <div class="form-group " ng-class="registerForm.username.$invalid ? '' : 'has-success'"> <div class="input-group"> <div class="input-group-addon"><span class=" iconfont icon-register icon-phone"></span></div> <input type="text" name="username" class="form-control" placeholder="请输入手机号码" ng-model="user.username" maxlength="11" required ng-pattern="/1[3|5|7|8|][0-9]{9}/" ng-focus/> </div> <div class="form-error" ng-show="(registerForm.username.$invalid && registerForm.username.$dirty && !registerForm.username.$focused) || (registerForm.username.$invalid && submitted )"> <span ng-show="registerForm.username.$error.required">手机号不能为空</span> <span ng-show="registerForm.username.$error.pattern">请输入正确的手机号码</span> </div> </div> <div class="form-group row sms-code-row"> <div class="col-xs-6 input-sms-code"> <input type="text" value="" name="sms_code" class="form-control" ng-model="user.sms_code" placeholder="请输入6位验证码" required ng-maxlength="6" maxlength="6"/> </div> <div class="col-xs-6 btn-sms-code"> <button type="button" class="btn btn-default btn-register btn-tianmi" ng-click="getVerifyCode(user.username)" ng-disabled="sms_code_status || registerForm.username.$invalid">{{sms_code_content}} </button> </div> <div class="clearfix"></div> <div class="form-error" ng-show="(registerForm.sms_code.$invalid && registerForm.sms_code.$dirty) ||(registerForm.sms_code.$invalid && submitted) "> <span ng-show="registerForm.sms_code.$error.required">请输入验证码</span> </div> </div> <div class="form-group"> <div class="input-group"> <div class="input-group-addon"><span class=" iconfont icon-register icon-key"></span></div> <input type="password" name="password" ng-model="user.password" class="form-control" placeholder="请输入登录密码" required ng-focus minlength="6" ng-pattern="/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,16}$/"/> </div> <div class="form-error" ng-show="(registerForm.password.$invalid && registerForm.password.$dirty && !registerForm.password.$focused) || (registerForm.password.$invalid && submitted)"> <span ng-show="registerForm.password.$error.minlength">密码不能少于6位</span> <span ng-show="registerForm.password.$error.pattern">密码必须由数字和字母组成</span> <span ng-show="registerForm.password.$error.required">密码不能为空</span> </div> </div> <div class="form-group"> <div class="input-group"> <div class="input-group-addon"><span class=" iconfont icon-register icon-key"></span></div> <input type="password" name="repeat_password" class="form-control" ng-model="user.repeat_password" ng-focus placeholder="请再次输入密码" required pw-check match="user.password"/> <!--<span class="iconfont icon-yonghu"></span>--> </div> <div class="form-error" ng-show="(registerForm.repeat_password.$invalid && registerForm.repeat_password.$dirty && registerForm.repeat_password.$focused) || (registerForm.repeat_password.$invalid && submitted)"> <span ng-show="registerForm.repeat_password.$error.required">密码不能为空</span> <span ng-show="registerForm.$error.matchError">两次密码不一样</span> </div> </div> <div class="form-group"> <div class="input-group"> <div class="input-group-addon"><span class=" iconfont icon-register icon-yonghu"></span></div> <input type="text" name="nick_name" class="form-control" ng-model="user.nick_name" placeholder="请输入昵称" minlength="2" maxlength="20" ng-focus ng-pattern="/^[a-zA-Z0-9\u0391-\uFFE5]{2,20}$/ " required/> </div> <div class="form-error" ng-show="(registerForm.nick_name.$invalid && registerForm.nick_name.$dirty && registerForm.nick_name.$focused) || (registerForm.nick_name.$invalid && submitted)"> <span ng-show="registerForm.nick_name.$error.required">昵称不能为空</span> <span ng-show="registerForm.nick_name.$error.pattern">昵称为2-20个字符,可由中文、字母和数字组成</span> </div> </div> <div class="checkbox"> <label> <input type="checkbox" name="protocol" ng-model="protocol" required> 同意 <a class="protocol" href="http://123.57.246.184/wordpress/?p=1941" target="_blank">添米用户注册协议</a> 和 <a class="protocol" href="http://123.57.246.184/wordpress/?p=1939" target="_blank">添米投资服务协议</a> </label> <div class="form-error" ng-show="!protocol && submitted"> <span>请先同意协议</span> </div> </div> <input type="submit" value="注册" class="btn btn-register btn-tianmi"/> {{result}} </form>
controller代码
$scope.submitted = false $scope.register = function (user) { //表单正常提交 if($scope.registerForm.$valid){ //正常提交表单 } else{ $scope.submitted = true; } };