AngularJS实现表单验证


Posted in Javascript onJanuary 28, 2015

虽然我不是前端程序员,但明白前端做好验证是多么重要。

因为这样后端就可以多喘口气了,而且相比后端什么的果然还是前端可以提高用户的幸福感。

AngularJS提供了很方便的表单验证功能,在此记录一番。

首先从下面这段代码开始

<form ng-app="myApp" ng-controller="validationController" name="mainForm" novalidate>

    <p>Email:

        <input type="email" name="email" ng-model="email" required>

        <span style="color:red" ng-show="mainForm.email.$dirty && mainForm.email.$invalid">

            <span ng-show="mainForm.email.$error.required">Email is required.</span>

            <span ng-show="mainForm.email.$error.email">Invalid email address.</span>

        </span>

    </p>

    <p>

        <input type="submit" ng-disabled="mainForm.$invalid">

    </p>

</form>

<script>

angular.module('myApp',[])

.controller('validationController', ['$scope',function($scope) {

    $scope.user = 'Kavlez';

    $scope.email = 'sweet_dreams@aliyun.com';

}]);

</script>

input标签的一些验证选项,通常和HTML5标记搭配使用。

必填

<input type="text" required />
长度

使用指令ng-minlength/ng-maxlength

<input type="text" ng-minlength="5" />
特定格式
例如电子邮件、URL、数字,将type设置为相应类型即可,例如:

<input type="email" name="email" ng-model="user.email" />

<input type="number" name="age" ng-model="user.age" />

<input type="url" name="homepage" ng-model="user.facebook_url" />

模式匹配

使用指令ng-pattern,例如:

<input type="text" ng-pattern="[a-z]" />

表单属性,通过这些属性可以更容易地对表单进行操作

pristine/dirty
表示是否已修改,例如

<form name="mainForm" ng-controller="orderController">

<input type="email" name="userEmail" ng-model="myEmail" />

    {{mainForm.userEmail.$pristine}}

    {{mainForm.userEmail.$dirty}}

</form>

以formName.fieldName.$pristine方式访问,input必须有ng-model声明。

valid/invalid

表示是否通过验证。

$error

表单验证信息,验证不通过时返回相应信息。

AngularJS为表单状态提供了相应地css class

.ng-pristine

.ng-dirty

.ng-valid

.ng-invalid

例如,让验证通过为绿色,失败为红色:

input.ng-valid {

    color: green;

}

input.ng-invalid {

    color: green;

}

给出的例子中仅仅是一个email的验证就写了这么多,如果再加几个field,再加几种不同的提示,再加上几个事件,代码会变得杂乱不堪。

事实上并不推荐这样做,我们有更好的方法。
就是使用angular-messages.js

首先,不要忘了这两步

<script src="angular-messages.js"></script>

angular.module('myApp', ['ngMessages'])

好,先用ng-messages和ng-message替换掉那些重复的东西,上面的例子变成:

<form ng-controller="validationController" name="mainForm" >

    <p>Email:

        <input 

        type="email" name="email" ng-model="myEmail" ng-minlength="3" ng-maxlength="50" required />

        <div style="color:red" ng-messages="mainForm.email.$error" ng-messages-multiple>

            <p class="error" ng-message="required">Email is required.</p>

            <p class="error" ng-message="email">Invalid email address.</p>

            <p class="error" ng-message="minlength">min length 10</p>

            <p class="error" ng-message="maxlength">max length 50</p>

        </div>

    </p>

    <p>

        <input type="submit" ng-disabled="mainForm.$invalid" />

    </p>

</form>

功能上没有任何变化,只是把重复的代码全部去掉了。
注意区分ng-messasges和ng-message,有没有感觉有点像with()? 后面的ng-messages-multiple,这里用作同时让多个提示出现。

但这样仍然不够好,就算省去了ng-message中的内容,但是多个field中都存在required验证时仍然会有重复。
而且,如果不同页面中的表单都涉及到相同的内容时重复的验证提示会越来越多。
为了解决这个问题,我们可以使用ng-messages-include指令。
该指令用来引用模板,比如上面的例子变为:

<form ng-controller="validationController" name="mainForm" >

    <p>Email:

        <input 

        type="email" name="email" ng-model="myEmail" ng-minlength="3" ng-maxlength="50" required />

        <div style="color:red" ng-messages="mainForm.email.$error" ng-messages-multiple ng-messages-include="validateTemplate/email.html">

        </div>

    </p>

    <p>

        <input type="submit" ng-disabled="mainForm.$invalid" />

    </p>

</form>

并不复杂,我们再加点东西。
为了让提示更友好(?)一些,我们试试实现光标离开后出现提示的效果。
这时候用指令(directive)会方便很多,在这里先涉及一点和指令相关的内容。

先运行起来再说:

var myApp = angular.module('myApp',[])

    .controller('validationController', ['$scope',function($scope) {

        $scope.user = 'Kavlez';

        $scope.email = 'sweet_dreams@aliyun.com';

    }])

    .directive('hintOnBlur', [function() {

        return {

            require: 'ngModel',

            link: function(scope, element, attrs, ctrl) {

                ctrl.focused = false;

                element.bind('focus', function(evt) {

                    scope.$apply(function() {ctrl.focused = true;});

                }).bind('blur', function(evt) {

                    scope.$apply(function() {ctrl.focused = false;});

                });

            }

        }

    }]);

此处我们用focused来判断光标是否在某个属性上,当使用了hintOnBlur指令的对象上发生focus或blur事件时focused的状态发生变化。

表单也跟着改变一下,使用方法如下:

<form ng-controller="validationController" name="mainForm" >

    <p>Email:

        <input type="email" name="email" ng-model="myEmail" ng-minlength="3" ng-maxlength="50" required hint-on-blur />

        <div style="color:red" ng-messages="mainForm.email.$error" ng-show="!mainForm.email.focused" ng-messages-multiple ng-messages-include="validateTemplate/email.html">

        </div>

    </p>

    <p>

        <input type="submit" ng-disabled="mainForm.$invalid" />

    </p>

</form>

在ng-show中再加入对focused的判断,false时出现提示。

现在看起来像那么回事了。
自定义验证方式与有效性(validity),这个也用到指令(directive)。
验证填写的email是否已占用,这里简单模拟一下:

.directive('isAlreadyTaken', function() {

    return {

        require: 'ngModel',

        link: function(scope, ele, attrs, ctrl) {

            ctrl.$parsers.push(function(val) {

                ctrl.$setValidity('emailAvailable', false);

                var emailTable = [

                    'K@gmail.com',

                    'a@gmail.com',

                    'v@gmail.com',

                    'l@gmail.com',

                    'e@gmail.com',

                    'z@gmail.com'];

                for (var i=0;i<emailTable.length;i+=1)

                    if(val==emailTable[i])

                        return;

                ctrl.$setValidity('emailAvailable', true);

                return val;

            })

        }

    }

})

Input元素中加上is-already-taken属性,并且再加一个ng-message:

<p class="error" ng-message="emailAvailable">Already taken! try other email addresses!</p>
Javascript 相关文章推荐
复制小说文本时出现的随机乱码的去除方法
Sep 07 Javascript
JavaScript 原型学习总结
Oct 29 Javascript
jquery删除提示框弹出是否删除对话框
Jan 07 Javascript
jQuery实现ichat在线客服插件
Dec 29 Javascript
详解用vue编写弹出框组件
Jul 04 Javascript
浅谈AngularJS中使用$resource(已更新)
Sep 14 Javascript
Vue CLI3搭建的项目中路径相关问题的解决
Sep 17 Javascript
vue实现路由懒加载及组件懒加载的方式
Jun 11 Javascript
在vue中把含有html标签转为html渲染页面的实例
Oct 28 Javascript
使用Promise封装小程序wx.request的实现方法
Nov 13 Javascript
JavaScript实现矩形块大小任意缩放
Aug 25 Javascript
node中使用shell脚本的方法步骤
Mar 23 Javascript
jQuery制作简单柱状图实例
Jan 28 #Javascript
js分页工具实例
Jan 28 #Javascript
js制作简易年历完整实例
Jan 28 #Javascript
Angularjs编写KindEditor,UEidtor,jQuery指令
Jan 28 #Javascript
调试JavaScript中正则表达式中遇到的问题
Jan 27 #Javascript
JavaScript插件化开发教程 (四)
Jan 27 #Javascript
JavaScript插件化开发教程 (三)
Jan 27 #Javascript
You might like
PHP中md5()函数的用法讲解
2019/03/30 PHP
jquery实现预览提交的表单代码分享
2014/05/21 Javascript
js简单判断flash是否加载完成的方法
2016/06/21 Javascript
D3.js实现文本的换行详解
2016/10/14 Javascript
JavaScript制作简单的框选图表
2017/05/15 Javascript
Vue 2中ref属性的使用方法及注意事项
2017/06/12 Javascript
jQuery实现炫丽的3d旋转星空效果
2018/07/04 jQuery
微信小程序之批量上传并压缩图片的实例代码
2018/07/05 Javascript
一文读懂ES7中的javascript修饰器
2019/05/06 Javascript
js实现转动骰子模型
2019/10/24 Javascript
jQuery实现倒计时功能完整示例
2020/06/01 jQuery
js实现点击烟花特效
2020/10/14 Javascript
Pyhton中防止SQL注入的方法
2015/02/05 Python
python实现将pvr格式转换成pvr.ccz的方法
2015/04/28 Python
Python如何实现守护进程的方法示例
2017/02/08 Python
Python正则表达式教程之一:基础篇
2017/03/02 Python
Python OpenCV利用笔记本摄像头实现人脸检测
2020/08/20 Python
pandas的qcut()方法详解
2019/07/06 Python
python函数的万能参数传参详解
2019/07/26 Python
python解释器安装教程的方法步骤
2020/07/02 Python
python中plt.imshow与cv2.imshow显示颜色问题
2020/07/16 Python
如何基于Python Matplotlib实现网格动画
2020/07/20 Python
Django如何继承AbstractUser扩展字段
2020/11/27 Python
拉斯维加斯酒店、演出、旅游、俱乐部及更多:Vegas.com
2019/02/28 全球购物
写好求职信第一句话的技巧
2013/10/26 职场文书
承认错误的检讨书
2014/01/30 职场文书
《难忘的泼水节》教学反思
2014/02/27 职场文书
青奥会口号
2014/06/12 职场文书
我的中国梦演讲稿800字
2014/08/19 职场文书
2014最新实习证明模板
2014/10/02 职场文书
财务部会计岗位职责
2015/02/03 职场文书
家属慰问信
2015/02/14 职场文书
魂断蓝桥观后感
2015/06/10 职场文书
《日月潭》教学反思
2016/02/20 职场文书
餐厅如何利用“营销策略”扭转亏本局面
2019/10/15 职场文书
python 实现两个变量值进行交换的n种操作
2021/06/02 Python