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 相关文章推荐
六款帮助你实现惊艳视差滚动效果的jQuery插件
Sep 14 Javascript
JavaScript判断访问的来源是手机还是电脑,用的哪种浏览器
Dec 12 Javascript
JavaScript中的普通函数与构造函数比较
Apr 07 Javascript
jQuery实现彩带延伸效果的网页加载条loading动画
Oct 29 Javascript
浅谈JavaScript的push(),pop(),concat()方法
Jun 03 Javascript
使用BootStrap建立响应式网页——通栏轮播图(carousel)
Dec 21 Javascript
原生js实现放大镜特效
Mar 08 Javascript
图解Javascript——作用域、作用域链、闭包
Mar 21 Javascript
修改 bootstrap table 默认detailRow样式的实例代码
Jul 21 Javascript
详解如何在vue-cli中使用vuex
Aug 07 Javascript
微信小程序登录数据解密及状态维持实例详解
May 06 Javascript
js Math数学简单使用操作示例
Mar 13 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
模仿OSO的论坛(二)
2006/10/09 PHP
PHP生成可点击刷新的验证码简单示例
2016/05/13 PHP
php通过文件头判断格式的方法
2016/05/28 PHP
PHP中类属性与类静态变量的访问方法示例
2016/07/13 PHP
Laravel框架执行原生SQL语句及使用paginate分页的方法
2018/08/17 PHP
JS验证控制输入中英文字节长度(input、textarea等)具体实例
2013/06/21 Javascript
JS实现从连接中获取youtube的key实例
2015/07/02 Javascript
Jquery1.9.1源码分析系列(十五)动画处理之外篇
2015/12/04 Javascript
全面解析JavaScript的Backbone.js框架中的Router路由
2016/05/05 Javascript
JavaScript实现多栏目切换效果
2016/12/12 Javascript
js实现表格筛选功能
2017/01/18 Javascript
NodeJs测试框架Mocha的安装与使用
2017/03/28 NodeJs
js分页之前端代码实现和请求处理
2017/08/04 Javascript
vue系列之动态路由详解【原创】
2017/09/10 Javascript
一个Vue页面的内存泄露分析详解
2018/06/25 Javascript
[47:50]Secret vs VP 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
用Python制作简单的朴素基数估计器的教程
2015/04/01 Python
Python自动化测试Eclipse+Pydev 搭建开发环境
2016/08/15 Python
python numpy 一维数组转变为多维数组的实例
2018/07/02 Python
Python 实现文件打包、上传与校验的方法
2019/02/13 Python
Django接收post前端返回的json格式数据代码实现
2019/07/31 Python
pytorch三层全连接层实现手写字母识别方式
2020/01/14 Python
Python中无限循环需要什么条件
2020/05/27 Python
Python使用Chrome插件实现爬虫过程图解
2020/06/09 Python
python 利用openpyxl读取Excel表格中指定的行或列教程
2021/02/06 Python
Python操作Excel的学习笔记
2021/02/18 Python
英国旅游额外服务市场领导者:Holiday Extras(机场停车场、酒店、接送等)
2017/10/07 全球购物
两年的个人工作自我评价
2014/01/10 职场文书
餐厅经理岗位职责范本
2014/02/17 职场文书
工商企业管理专业自荐信范文
2014/04/12 职场文书
2014年妇产科工作总结
2014/12/08 职场文书
2014年终个人总结报告
2015/03/09 职场文书
销售员自我评价
2015/03/11 职场文书
2015军训通讯稿大全
2015/07/18 职场文书
2015年学校综合治理工作总结
2015/07/20 职场文书
一起来学习Python的元组和列表
2022/03/13 Python