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 相关文章推荐
图片自动更新(说明)
Oct 02 Javascript
基于JQuery制作的产品广告效果
Dec 08 Javascript
jquery实现的一个导航滚动效果具体代码
May 27 Javascript
js showModalDialog参数的使用详解
Jan 07 Javascript
jquery.form.js用法之清空form的方法
Mar 07 Javascript
JavaScript常用小技巧小结
Dec 29 Javascript
AngularJS学习笔记之基本指令(init、repeat)
Jun 16 Javascript
jQuery实现的点赞随机数字显示动画效果(附在线演示与demo源码下载)
Dec 31 Javascript
浅析node.js的模块加载机制
May 25 Javascript
Angular7中创建组件/自定义指令/管道的方法实例详解
Apr 02 Javascript
详解JavaScript 的执行机制
Sep 18 Javascript
vue-router懒加载的3种方式汇总
Feb 28 Vue.js
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
验证token、回复图文\文本、推送消息的实用微信类php代码
2016/06/28 PHP
PHP去除空数组且数组键名重置的讲解
2019/02/28 PHP
网站上面有这种切换效果
2006/06/26 Javascript
从JavaScript 到 JQuery (1)学习小结
2009/02/12 Javascript
JavaScript 开发中规范性的一点感想
2009/06/23 Javascript
DOM和XMLHttpRequest对象的属性和方法整理
2012/01/04 Javascript
js中继承的几种用法总结(apply,call,prototype)
2013/12/26 Javascript
jQuery实用技巧必备(中)
2015/11/03 Javascript
jQuery获取同级元素的简单代码
2016/07/09 Javascript
基于angularjs实现图片放大镜效果
2016/08/31 Javascript
socket.io学习教程之深入学习篇(三)
2017/04/29 Javascript
JS实现不用中间变量temp 实现两个变量值得交换方法
2018/02/04 Javascript
vue左右侧联动滚动的实现代码
2018/06/06 Javascript
Vue无限滑动周选择日期的组件的示例代码
2018/07/18 Javascript
JavaScript中创建原子的方法总结
2018/08/26 Javascript
react写一个select组件的实现代码
2019/04/03 Javascript
webpack常用构建优化策略小结
2019/11/21 Javascript
关于angular 8.1使用过程中的一些记录
2020/11/25 Javascript
简单文件操作python 修改文件指定行的方法
2013/05/15 Python
ubuntu环境下python虚拟环境的安装过程
2018/01/07 Python
Python实现爬虫从网络上下载文档的实例代码
2018/06/13 Python
Python学习笔记之自定义函数用法详解
2019/06/08 Python
python中break、continue 、exit() 、pass终止循环的区别详解
2019/07/08 Python
正则给header的冒号两边参数添加单引号(Python请求用)
2019/08/09 Python
python 表格打印代码实例解析
2019/10/12 Python
在python3.9下如何安装scrapy的方法
2021/02/03 Python
利用CSS3实现的文字定时向上滚动
2016/08/29 HTML / CSS
Craghoppers德国官网:户外和旅行服装
2020/02/14 全球购物
大学生实习自我鉴定
2013/12/11 职场文书
普通话宣传标语
2014/06/26 职场文书
消费者投诉书范文
2015/07/02 职场文书
小学远程教育工作总结
2015/08/13 职场文书
python中requests库+xpath+lxml简单使用
2021/04/29 Python
Nginx速查手册及常见问题
2022/04/07 Servers
SpringBoot接入钉钉自定义机器人预警通知
2022/07/15 Java/Android
利用Python脚本写端口扫描器socket,python-nmap
2022/07/23 Python