之前说过了angular是如何给表单的数据进行基本的,常用的验证的:angular学习笔记(二十)-表单验证

但是在实际工作中,这些验证是远远不够的,很多时候我们需要自定义一些验证规则,以及一些异步,需要向后台发送请求的验证.

这篇文章就来讲解,如何自定义验证规则.

同时,这篇文章还是angular指令中使用ngModelController中关于 $validators 属性和 $asyncValidators 和 $pending 属性的详细讲解.

首先,需要自定义指令,设置require属性为'?^ngModel',在指令的link函数中通过第四个参数ctrl,获取到ngModelController这个东西.

ngModelController实例有两个对象,一个是 $validators对象,一个是 $asyncValidators对象.当我们需要添加自定义的同步验证规则时,使用$validators对象,当我们需要添加自定义的异步验证规则时,使用$asyncValidators对象.

通过栗子来说明:

html:

<!DOCTYPE html>
<html ng-app="customControl">
<head>
<title>asyncValidators</title>
<meta charset="utf-8">
<script src="angular-1.3.2.js"></script>
<script src="script.js"></script>
<link type="text/css" href="bootstrap.css" rel="stylesheet" />
<style>
*{font-family: 'MICROSOFT YAHEI'}
</style>
</head>
<body>
<div class="container" ng-controller="ctrl">
<div class="page-header">
<h1>ngModelController- <small>asyncValidators实现异步验证表单</small></h1>
</div>
<form role="form" name="myForm">
<div class="form-group">
<input validate-name type="text" name="myWidget" ng-model="userContent" ng-model-options="{updateOn:'blur'}" class="form-control" required>
</div>
<div class="alert alert-danger" role="alert" ng-show="myForm.myWidget.$error.required">
<strong>Oh!</strong> 必填!
</div>
<div class="alert alert-danger" role="alert" ng-show="myForm.myWidget.$error.validCharacters">
<strong>Oh!</strong> 不符合自定义的验证规则!
</div>
<div class="alert alert-danger" role="alert" ng-show="myForm.myWidget.$error.uniqueUsername">
<strong>Oh!</strong> 已经存在的用户名!
</div>
</form>
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">用户名:</h3>
</div>
<div class="panel-body">
{{userContent}}
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">正在异步验证中:</h3>
</div>
<div class="panel-body">
{{myForm.myWidget.$pending}}
</div>
</div>
</div> </body>
</html>

这段html里,input元素使用了validate-name这个指令,后面在js中我们会通过这个指令来给它添加验证.注意元素必须要有ng-model属性,否则也没有什么意义了...

这个指令我们共验证三项,且在元素失去焦点的时候进行验证:

1.required  : ng内置的的验证,需要在指令的最后添加required属性. 然后自己指令里什么也不用写,就可以验证它是否为空了.

2.validCharacters: 自定义的一个同步验证规则,验证输入的内容是否包含'bunny'字符串,自定义的验证不需要在指令最后添加validCharacters属性

3.uniqueUsername: 自定义的一个异步验证规则,验证输入的用户名是否已经被注册,同样,自定义的规则不需要在指令的最后添加uniqueUsername属性

然后来看js代码:

var app = angular.module('customControl',[]);
app.controller('ctrl',function($scope){
}); app.directive('validateName',function($http,$q){
return {
restrict:'A',
require:'?^ngModel',
link:function(scope,iele,iattr,ctrl){
ctrl.$validators.validCharacters = function(modelValue, viewValue) {
var value = modelValue || viewValue;
return value ? value.indexOf('bunny')!==-1 : true
};
ctrl.$asyncValidators.uniqueUsername = function(modelValue, viewValue) {
var value = modelValue || viewValue;
// Lookup user by username
return $http.get('/api/users/' + value).
then(function resolved(res) {
if(res.data){
//用户名已经存在,验证失败,给下一个promise传递失败通知.
return $q.reject('res.data');
}
else {
//用户名不存在,验证成功.
return true
} }, function rejected() { })
};
}
}
});

先说 validCharacters 验证: 我们给ctrl(也就是ngModelController的实例)的$validators属性添加了validCharacters属性,它的属性值为一个函数,函数接受两个参数modelValue和viewValue,这两个参数具体分别代表什么,请入angular指令中使用ngModelController查看,总之,这里可以认为就是input的value值.然后我们通过这个自定义的函数的返回值来确定是否通过验证,如果是true,则通过验证,如果是false,则不通过验证,在不通过验证的时候,$error.validCharacters就会为true.

同理,来看uniqueUsername 验证:我们给ctrl的$asyncValidators属性添加了uniqueUsername属性,它的属性值为一个函数,函数接受的参数也同上,然后我们通过$http发送请求来验证用户名是否存在:

node代码:

var express = require('express');
var app = express(); app.use(express.static(__dirname+''));
app.use(express.bodyParser());
app.use(express.methodOverride()); var names = [
'code_bunny','mi_bunny','hua_bunny'
]; app.get('/api/users/:name',function(req,res){
setTimeout(function(){
var name = req.params.name;
names.forEach(function(list){
if(name==list) {
res.send(list);
}
else {
res.end()
}
});
},1000);
}); app.listen(9000);

我们故意延迟了1000毫秒再给出响应,这样,在等待响应的时间里,我们可以看到myForm.myWidget.$pending发生的变化:

当得到响应后,它就会变为空.

所以,$pending属性里放置的是所以正在等待响应的异步验证.

最重要的一点,$asyncValidators的验证函数返回值比如是一个promise对象.根据这个promise对象发出的通知来决定验证是成功还是失败.如果发出的是失败通知,那么它就是验证失败,比如这里的$q.reject().如果发出的是成功通过,那么他就是验证成功,比如这里的return false.

这里要注意promise的用法:由于$http.get()返回的promise,无论执行的是resolved函数还是rejected函数,他发送给下一个promise的通知总是成功的,所以为了发送失败通知,必须使用$q.reject().

另外,我本来想尝试如果能搜索到用户名,则返回搜索到的用户名,如果不能,则不返回,让它接收到404状态,然后调用rejected函数,但是没能成功,因为如果不返回,它会请求很长一段时间才算请求失败,而不是一旦发现找不到就立刻算请求失败了.所以这里还是根据搜索结果返回不同值来进行判断.

完整代码: https://github.com/OOP-Code-Bunny/angular/tree/master/ngModelController/asyncValidators

 

angular中的表单数据自定义验证的更多相关文章

  1. angular中的表单验证

    angular中的表单验证很强大, 一共有5中验证信息,$valid,$invalid,$pristine,$dirty,$error. $valid-----当验证通过的时候,为true,不通过的时 ...

  2. Vue学习之--------Vue中收集表单数据(使用v-model 实现双向数据绑定、代码实现)(2022/7/18)

    文章目录 1.Vue中实现表单数据的收集 1.1 基础知识 1.2 代码实例 1.3 测试效果 1.4 额外插一嘴 1.Vue中实现表单数据的收集 1.1 基础知识 表单中常用的标签:input(输入 ...

  3. strus2中获取表单数据 两种方式 属性驱动 和模型驱动

    strus2中获取表单数据 两种方式 属性驱动 和模型驱动 属性驱动 /** * 当前请求的action在栈顶,ss是栈顶的元素,所以可以利用setValue方法赋值 * 如果一个属性在对象栈,在页面 ...

  4. layer.open弹框中的表单数据无法获取

    layer.open弹框中的表单数据无法获取 表单数据模板 layer.open() 页面效果: 当点击确定后,radio和textarea获取的值总是为空,解决办法: var setPriCustB ...

  5. gin中绑定表单数据至自定义结构体

    package main import "github.com/gin-gonic/gin" type StructA struct { FieldA string `form:& ...

  6. Angular11 模板表单、响应式表单(自定义验证器)、HTTP、表单元素双向绑定

    1 模板表单 模型通过指令隐式创建 技巧01:需要在模块级别引入 FormsModule ,通常在共享模块中引入再导出,然后在需要用到 FormsModule 的模块中导入共享模块就可以啦 impor ...

  7. Action 中获取表单数据的三种方式

    (尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/53138905  冷血之心的博客) Action 中获取表单提交数据 ...

  8. iview表单密码自定义验证

    From中定义   ref="passwordForm" 获取dom节点  :model="passwordForm" 关联表单数据对象 :rules=&quo ...

  9. easyui 表单和自定义验证扩展和js自定义返回值

    ================jsp==========================<form  method="post" id="regfrminp&qu ...

随机推荐

  1. spark的外排:AppendOnlyMap与ExternalAppendOnlyMap

    相信很多人和我一样, 在控制台中总是可以看到会打印出如下的语句: INFO ExternalAppendOnlyMap: Thread 94 spilling in-memory map of 63. ...

  2. 分布式交易系统的并发处理, 以及用Redis和Zookeeper实现分布式锁

    交易系统 交易系统的数据结构 支付系统API通常需要一个“订单号”作为入参, 而实际调用API接口时使用到的往往不是真正意义的业务订单号, 而是交易订单号.  支付系统的API会使用“商户号+订单号” ...

  3. Spring Cloud环境搭建: Eureka Server

    项目目录结构, 总共三个文件 ├── pom.xml └── src ├── main │   ├── java │   │   └── com │   │   └── rockbb │   │   ...

  4. HOOK 底层键盘消息---WH_KEYBOARD_LL

    代码:屏蔽三个全局快捷键 代码的作用是屏蔽掉凝视中的三个快捷键. LRESULT CALLBACK LowLevelKeyboardProc (INT nCode, WPARAM wParam, LP ...

  5. 删除草稿信息之后 threads表的数据没有发生变化

    现象描述: 无论是用_id来删除草稿信息,还是用thread_id和type来删除草稿,草稿都可以删除掉,但是threads表中的数据都没有发生变化. private void removeDraft ...

  6. 【MySQL】局域网内:在一台电脑访问另一台电脑的mysql数据库

    1. 假设192.168.1.3为服务器2. 首先在ip为192.168.1.103的机子上能够ping 通运行->cmd>ping 192.168.1.3检查是否能ping通3. 把两台 ...

  7. MATLAB R2018a 安装教程

    1.下载相应的 MATLAB  R2018a  版本如下:[matlab2018的百度云盘:链接:https://pan.baidu.com/s/1OV242y6EV6auvG3DvvqD8A 密码: ...

  8. golang学习笔记 ---面向并发的内存模型

    Go语言是基于消息并发模型的集大成者,它将基于CSP模型的并发编程内置到了语言中,通过一个go关键字就可以轻易地启动一个Goroutine,与Erlang不同的是Go语言的Goroutine之间是共享 ...

  9. SharePoint 2013 创建Web Application

    今天继续SharePoint 2013 的探索之旅,之前几篇文章分析了SharePoint 2013的物理拓扑结构,安装,以及逻辑体系结构.在这篇文章中,我将继续Step By Step形式演示如何在 ...

  10. MySQL的启动与停止

    如果MySQL数据库是自己安装的,可以用如下方法分别启动和停止MySQL. 1. MySQL服务器的启动 $mysql_dir/bin/mysqld_safe &         (其中&am ...