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 15 Javascript
JavaScript中string转换成number介绍
Dec 31 Javascript
使用Node.js处理前端代码文件的编码问题
Feb 16 Javascript
一种Javascript解释ajax返回的json的好方法(推荐)
Jun 02 Javascript
关于JS 预解释的相关理解
Jun 28 Javascript
Bootstrap表单布局样式源代码
Jul 04 Javascript
利用策略模式与装饰模式扩展JavaScript表单验证功能
Feb 14 Javascript
Vue中定义全局变量与常量的各种方式详解
Aug 23 Javascript
jQuery内容选择器与表单选择器实例分析
Jun 28 jQuery
使用VScode 插件debugger for chrome 调试react源码的方法
Sep 13 Javascript
jquery.tagsinput.js实现记录checkbox勾选的顺序
Sep 21 jQuery
AutoJs实现刷宝短视频的思路详解
May 22 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
终于听上了直流胆调频
2021/03/02 无线电
php中var_export与var_dump的区别分析
2010/08/21 PHP
PHP中把有符号整型转换为无符号整型方法
2015/05/27 PHP
Yii2 hasOne(), hasMany() 实现三表关联的方法(两种)
2017/02/15 PHP
thinkphp框架实现路由重定义简化url访问地址的方法分析
2020/04/04 PHP
php使用Swoole实现毫秒级定时任务的方法
2020/09/04 PHP
jQuery中判断一个元素是否为另一个元素的子元素(或者其本身)
2012/03/21 Javascript
Javascript基础 函数“重载” 详细介绍
2013/10/25 Javascript
javascript中apply和call方法的作用及区别说明
2014/02/14 Javascript
js写的方法实现上传图片之后查看大图
2014/03/05 Javascript
express的中间件bodyParser详解
2014/12/04 Javascript
javascript函数命名的三种方式及区别介绍
2016/03/22 Javascript
H5用户注册表单页 注册模态框!
2016/09/17 Javascript
JS限定手机版中图片大小随分辨率自动调整的方法
2016/12/05 Javascript
微信小程序 页面传值详解
2017/03/10 Javascript
详解axios在vue中的简单配置与使用
2017/05/10 Javascript
解决Extjs下拉框不显示的问题
2017/06/21 Javascript
解决vue打包之后静态资源图片失效的问题
2018/02/21 Javascript
详解vue-loader在项目中是如何配置的
2018/06/04 Javascript
Node.js中读取TXT文件内容fs.readFile()用法
2018/10/10 Javascript
vue 使用高德地图vue-amap组件过程解析
2019/09/07 Javascript
纯Python开发的nosql数据库CodernityDB介绍和使用实例
2014/10/23 Python
实例讲解Python中函数的调用与定义
2016/03/14 Python
Python cookbook(数据结构与算法)找出序列中出现次数最多的元素算法示例
2018/03/15 Python
pyqt5的QComboBox 使用模板的具体方法
2018/09/06 Python
python kafka 多线程消费者&amp;手动提交实例
2019/12/21 Python
Python爬虫抓取指定网页图片代码实例
2020/07/24 Python
利用Bootstrap实现漂亮简洁的CSS3价格表实例源码
2017/03/02 HTML / CSS
AmazeUI图片轮播效果的示例代码
2020/08/20 HTML / CSS
Ann Taylor官方网站:美国最大的女性产品制造商之一
2016/09/14 全球购物
销售业务实习自我鉴定
2013/09/23 职场文书
写好自荐信的要点
2013/11/06 职场文书
《爱如茉莉》教后反思
2014/04/12 职场文书
学校消防安全责任书
2014/07/23 职场文书
企业年检委托书范本
2014/10/14 职场文书
开机音效回归! Windows 11重新引入开机铃声
2021/11/21 数码科技