本章主要是讲指令与ngModel的交互。

在angular有一个内置指令叫ngModel,它是angular用来处理表单的最重要的指令。在源码中,页面上的model值的格式化、解析、验证都是由ngModel指令所对应的控制器ngModelController来实现的。ngModelController提供了很多方法和属性,我们可以通过自定义指令的require:'ngModel'来获取内置指令ngModel的ngModelController,进而在link函数里对操作ngModelController的方法和属性。

接下来具体讲一下ngModelController的方法和属性,以及它们的具体用法。

1.两个核心属性$viewValue和$modelValue 
$viewValue是指令渲染模板所用的值,而$modelValue是在控制器中流通的值。很多时候这两个值是不一样的。比如说,当页面上展示了一个日期,显示的可能是"2018/04/23",但是这个字符串在控制器中对应的值可能是一个js的Date对象的实例。

2.三个核心管道$formatters $parses $validators 和$asyncValidators 

angular除了提供$viewValue和\modelValue之外,还提供了两个用来处理它们的方法,分别是$parses和$formatters。 
$parsers:由view值到model值的转换器,用户输入的变化会触发其中的管道函数,页面上的model值由管道函数中的return值决定。 
$formatters:和$parsers的作用相反,它是model值到view值的转化器,其view值由对应的管道函数中的return值决定。 
$validators: 是一个json对象

{
validateName: function(modelValue,viewValue){
return ...
}
}

当$setViewValue(value)被赋值给$modelValue之前,会经过$parsers管道,经过$parsers管道时,就会经过这个$validators管道。其中,validateName是验证器的名称,其中的参数modelValue和viewValue就是和viewValue,如果返回值是true,则通过validateName。 
自定义一个验证器:

<div class="alert alert-danger" role="alert" ng-show="myForm.myWidget.$error.validCharacters">
<strong>Oh!</strong> 不符合自定义的验证规则!
</div>
ngModel.$validators.validCharacters = function(modelValue, viewValue) {
var value = modelValue || viewValue;
return /[0-9]+/.test(value);
};

$asyncValidators:也是一个json对象,不过可以用来处理异步验证。

<input validate-name type="text" name="myWidget" ng-model="userContent" ng-model-options="{updateOn:'blur'}" class="form-control" required uniqueUsername>

<div class="alert alert-danger" role="alert" ng-show="myForm.myWidget.$error.uniqueUsername">
<strong>Oh!</strong> 已经存在的用户名!
</div>
app.directive('validateName',function($http,$q){
return {
restrict:'A',
require:'?^ngModel',
link:function(scope,iele,iattr,ctrl){
ctrl.$asyncValidators.uniqueUsername = function(modelValue, viewValue) {
var value = modelValue || viewValue;
// 异步验证用户名是否已经存在
return $http.get('/api/users/' + value).
then(function resolved(res) {
if(res.data){
//用户名已经存在,验证失败,给下一个promise传递失败通知.
return $q.reject('res.data');
}
else {
//用户名不存在,验证成功.
return true
} }, function rejected() {
//请求失败
})
};
}
}
});

3.两个核心方法$setViewValue()和$render() 
$setViewValue(): 更新视图值。原因是每个input的输入事件都会调用这个方法。但是如果value是一个对象,而不是字符串或数值,那么我们在用该方法传入值之前应该先拷贝一份,因为ngModel不会深入检测对象的变化,它只看对象的引用是否发生变化。如果只是改变了对象的某个属性,也不会去经过$parsers和$validators管道。执行$setViewValue()方法,不会触发$digest。 
$render():在视图需要被更新的时候调用。由于ngModel的对比机制,$render()只在$modelValue和$viewValue都发生了实际的改变, 才会会被调用。也就是说,$render函数负责将模型值同步到视图上。

来看一下指令和控制器及其内部运作如图: 

还有一些常用属性

属性 说明
$error json对象。就是所有验证失败的验证名和失败信息组成的json对象。
$pending json对象。正在进行中的异步验证会被放在这个对象里。
$untouched 布尔值。如果元素还没有失去过焦点,那这个值就是true。
$touched 布尔值。如果元素已经失去过焦点,那这个值就是false。
$pristine 布尔值。如果元素还没有和用户发生过交互,那这个值就是true。
$dirty 布尔值。如果元素已经和用户发生过交互,那这个值就是true。
$valid 布尔值。这个也很常用,就是当所有验证(异步同步),都通过的时候,它就是true。
$invalid 布尔值。这个也很常用,就是当所有验证(异步同步),其中有一个或一个以上验证失败,它就是true。
$name 字符串。很简单,就是获取元素的name属性。
$isEmpty 当我们需要判断input的value值是否为空的时候,可以使用这个方法。

directive指令二 require:'^ngModel'的更多相关文章

  1. 学习AngularJs:Directive指令用法(完整版)

    这篇文章主要学习AngularJs:Directive指令用法,内容很全面,感兴趣的小伙伴们可以参考一下   本教程使用AngularJs版本:1.5.3 AngularJs GitHub: http ...

  2. AngularJs:Directive指令用法

    摘自:http://www.jb51.net/article/83051.htm 摘要:Directive(指令)是AngularJ非常强大而有有用的功能之一.它就相当于为我们写了公共的自定义DOM元 ...

  3. angularjs中directive指令与component组件有什么区别?

     壹 ❀ 引 我在前面花了两篇博客分别系统化介绍了angularjs中的directive指令与component组件,当然directive也能实现组件这点毋庸置疑.在了解完两者后,即便我们知道co ...

  4. 学习AngularJs:Directive指令用法

    跟我学AngularJs:Directive指令用法解读(上) http://blog.csdn.net/evankaka/article/details/51232895 跟我学AngularJs: ...

  5. angular上传获取图片的directive指令

    在AngularJS中,操作DOM一般在指令中完成,那么指令是如何实现的呢?指令的作用是把我们自定义的语义化标签替换成浏览器能够认识的HTML标签 一般的事件监听是在对静态的dom绑定事件,而如果在指 ...

  6. AngularJS中Directive指令系列 - 基本用法

    参考: https://docs.angularjs.org/api/ng/service/$compile http://www.zouyesheng.com/angular.html Direct ...

  7. 关于Angularjs写directive指令传递参数

    包子又来啦.... 在Angularjs当中,我们可能会经常要写directive指令.但是指令如果要共用的话,肯定是有细微的差别的,所以这些差别可能需要一个参数来决定 所以如何在指令中传递参数呢.. ...

  8. Angularjs之directive指令学习笔记(二)

    1.Directive的五个实例知道driective作用.其中字段restrict.template. replace.transclude.link用法 参考文章链接地址:http://damoq ...

  9. angularjs指令(二)

    最近学习了下angularjs指令的相关知识,也参考了前人的一些文章,在此总结下. 欢迎批评指出错误的地方.   Angularjs指令定义的API AngularJs的指令定义大致如下 angula ...

随机推荐

  1. Elasticsearch部分节点不能发现集群(脑裂)问题处理

    **现象描述** es1,es2,es3三台es组成一个集群,集群状态正常, 当es1 服务器重启后,es1不能加到集群中,自己选举自己为master,这就产生了es集群中所谓的“脑裂” , 把es1 ...

  2. Linux which/whereis/locate命令详解

    which 查看可执行文件的位置,从全局环境变量PATH里面查找对应的路径,默认是找 bash内所规范的目录 whereis 查看文件的位置,配合参数-b,用于程序名的搜索,从linux数据库查找. ...

  3. java 和 javascript CryptoJS 进行HmacSHA1加密

    import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.Invali ...

  4. C# Socket编程 笔记,Socket 详解,入门简单

    目录 一,网络基础 二,Socket 对象 三,Bind() 绑定与 Connect() 连接 四,Listen() 监听请求连接 和 Accept() 接收连接请求 五,Receive() 与 Se ...

  5. windows 2012R2 上必须要用sharepoint 2013 sp1.

    已经确认. 虽然有人讲以下powershell可以帮助安装sharepoint 2013. 不过不是每次都可以的 Import-Module ServerManager Add-WindowsFeat ...

  6. 红黑树及其实例JDK中的TreeMap

    红黑树是一种自平衡二叉查找树(binary search tree,BST),红黑树是一种比较复杂的数据结构,红黑树查找.插入.删除元素的时间复杂度为O(log n),n是树中元素的数目.文章的要讲的 ...

  7. 我的开源项目——Jerry

    在日常工作中,经常会碰到一些问题,比如数字金额要写成千分位形式(1234 -> 123,4.00).要写成汉字大写形式(123 -> 壹佰贰拾叁圆),又比如要进行 cookie 读写操作, ...

  8. C#调取webapi

    //定义参数 C#调取webapi var content = new FormUrlEncodedContent(new Dictionary<string, string>() { { ...

  9. Linux - 版本控制系统SVN

    0. 摘要 本文通过搭建SVN多版本库为例,介绍SVN的使用. SVN是一个集中式版本控制系统,在服务端部署中央版本库,所有开发人员客户端连接到中央版本库进行代码的提交和更新. Apache Subv ...

  10. IS服务器下做301永久重定向设置方法

    以前也没怎么关注301重定向,第一因为没有网站要重定向,第二对于不带www的域名我都是用的转发到带www的域名. 不过一场风波之后,很多服务商已经不提供转发服务了,虽说易名现在还可以享用到免费的转发服 ...