本章主要是讲指令与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. [翻译] ValueTrackingSlider

    ValueTrackingSlider What is it? A UISlider Subclass that displays live values in a popUpView. It’s i ...

  2. 超简易复制Model对象(为后续备忘录设计模式博文做铺垫)

    超简易复制Model对象(为后续备忘录设计模式博文做铺垫) 复制整个Model需要实现NSCopy协议,可以想象是非常麻烦的一件事情,今天我跟大家分享一个不需要你做任何操作的复制Model对象的方法, ...

  3. JAVA入门之程序设计环境搭建

    这篇文章写给刚接触或者想学JAVA的新朋友.学习JAVA,需要找一本好的入门书籍,推荐<Java从入门到精通>,然后就是JAVA程序设计开发环境的搭建. 首先,我们需要安装JAVA开发工具 ...

  4. (转)Matlab矩阵的简单操作

    转自:http://blog.sina.com.cn/s/blog_6264e23a0100veeq.html

  5. Spring+微信小程序 卡券打通

    近期公司项目需要使用到微信卡券模块,主要做的是在小程序打通微信卡券,实现小程序领取卡券的功能效果. 简单说下涉及的东西: Springboot—使用springboot做后端接口,非常便捷 并且根本是 ...

  6. 移动端上下滑动事件之--坑爹的touch.js

    下面的方法,不知道是操作方法不对还是啥.  在 zepto.js 里面加那一段代码不起作用 百度的 touch.js 是可以用的,但是使用方式 和 zepto有点不一样. 解决方案:参照这个链接地址 ...

  7. IM——技术方案

    一. 即时通讯技术方案 1. 第三方SDK: 环信, 融云, 网易云信, 腾讯 中小型公司/初创型: 建议使用第三方. 好处: 快, 符合快速开发的需求, 自己和后台人员不需要做什么操作 缺点: 你的 ...

  8. singleton和prototype的区别

    singleton作用域:当把一个Bean定义设置为singleton作用域是,Spring IoC容器中只会存在一个共享的Bean实例,并且所有对Bean的 请求,只要id与该Bean定义相匹配,则 ...

  9. 判断是否是微信浏览器JavaScript代码

    function isWeiXin(){     var ua = window.navigator.userAgent.toLowerCase();     if(ua.match(/MicroMe ...

  10. shell基础--变量的数值计算

    变量的数值计算 1.$((表达式)) (1).实验1 [root@~_~ day4]# cat test.sh #!/bin/bash a=6 b=2 echo "a-b=$(($a-$b) ...