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 相关文章推荐
xml 与javascript结合的问题解决方法
Mar 24 Javascript
Javascript 面向对象特性
Dec 28 Javascript
基于prototype扩展的JavaScript常用函数库
Nov 30 Javascript
jquery预览图片实现鼠标放上去显示实际大小
Jan 16 Javascript
jquery合并表格中相同文本的相邻单元格
Jul 17 Javascript
js实现倒计时效果(小于10补零)
Mar 08 Javascript
Node.JS 循环递归复制文件夹目录及其子文件夹下的所有文件
Sep 18 Javascript
浅谈Emergence.js 检测元素可见性的 js 插件
Nov 18 Javascript
JS实现延迟隐藏功能的方法(类似QQ头像鼠标放上展示信息)
Dec 28 Javascript
vue加载完成后的回调函数方法
Sep 07 Javascript
angular4 获取wifi列表中文显示乱码问题的解决
Oct 20 Javascript
Vue加载json文件的方法简单示例
Jan 28 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&amp;MYSQL留言板源码
2020/07/19 PHP
PHP+SQL 注入攻击的技术实现以及预防办法
2011/01/27 PHP
php正则取img标记中任意属性(正则替换去掉或改变图片img标记中的任意属性)
2013/08/13 PHP
php生成扇形比例图实例
2013/11/06 PHP
php实现扫描二维码根据浏览器类型访问不同下载地址
2014/10/15 PHP
PHP函数func_num_args用法实例分析
2015/12/07 PHP
jscript之List Excel Color Values
2007/06/13 Javascript
Open and Print a Word Document
2007/06/15 Javascript
往光标所在位置插入值的js代码
2013/09/22 Javascript
动态创建script标签实现跨域资源访问的方法介绍
2014/02/28 Javascript
如何防止回车(enter)键提交表单
2014/05/11 Javascript
JavaScript学习笔记之Function对象
2015/01/22 Javascript
bootstrap实现弹窗和拖动效果
2016/01/03 Javascript
详解Javascript ES6中的箭头函数(Arrow Functions)
2016/08/24 Javascript
正则验证小数点后面只能有两位数的方法
2017/02/28 Javascript
微信小程序之页面拦截器的示例代码
2017/09/07 Javascript
详解mpvue开发小程序小总结
2018/07/25 Javascript
Ant-design-vue Table组件customRow属性的使用说明
2020/10/28 Javascript
[58:18]2018DOTA2亚洲邀请赛3月29日 小组赛B组 iG VS Mineski
2018/03/30 DOTA
win10系统中安装scrapy-1.1
2016/07/03 Python
Python3调用微信企业号API发送文本消息代码示例
2017/11/10 Python
python简单图片操作:打开\显示\保存图像方法介绍
2017/11/23 Python
Python Matplotlib实现三维数据的散点图绘制
2019/03/19 Python
Python itertools.product方法代码实例
2020/03/27 Python
python小程序之4名牌手洗牌发牌问题解析
2020/05/15 Python
django 实现后台从富文本提取纯文本
2020/07/02 Python
python里反向传播算法详解
2020/11/22 Python
康帕斯酒店预订:Compass Hospitality(支持中文)
2018/08/23 全球购物
活动策划邀请函
2014/02/06 职场文书
十佳护士获奖感言
2014/02/18 职场文书
《菜园里》教学反思
2014/04/17 职场文书
品质标语大全
2014/06/21 职场文书
2014年教师节寄语
2014/08/11 职场文书
2015年教学管理工作总结
2015/05/20 职场文书
篮球拉拉队口号
2015/12/25 职场文书
Redis Cluster集群动态扩容的实现
2021/07/15 Redis