参考

https://docs.angularjs.org/api/ng/type/ngModel.NgModelController

https://docs.angularjs.org/api/ng/type/form.FormController

angular 提供了表单指令,它和ngModel 经常一起工作,所以一起介绍。

我们先来了解一下基本的ng-model

ng-model 作用是double binding

ng-model 在不同的element上会有不同的同步模式,这些angular已经帮我封装了许多.

当然 angular 也提供了一些方法在 ngModel 这个指令的 controller中(名为 ngModel),使得我们可以在自己的控件 (e.g. : checkBoxList, dropDownList) 也做double binding

此外 ng-model 还有一些基本 option 可以设置(1.3才有)

<input type="text" name="userName"
ng-model="user.name"
ng-model-options="{ updateOn: 'blur', debounce: 1000 ,getterSetter: true }"/><br />
<pre>user.name = <span ng-bind="user.name()"></span></pre>

updateOn 写入一个事件名来表示我们希望什么事件促使这个elem被更新,比如 blur / keyup 等

debounce 是deley update 毫秒, 一般我们不希望用户联系每一次keydown时都更新,而是等到用户停止输入时才执行一次更新。就可以放一个delay 实现了

getterSetter = true 可以用在依赖属性上,比如我们的$scope.name = function (){ retrun xx; } 当name是个方法的时候

我们再来看看 ng-model controller 还有些什么属性方法

ngModel controller

                     var ngModelController = {
"$viewValue": "12", //界面显示的数据
"$modelValue": "12", //$scope的value
"$parsers": [null, null], //这里的null是因为json无法看到,是 function 来的
"$formatters": [null, null],
"$viewChangeListeners": [null],
"$pristine": false,
"$dirty": true,
"$valid": true,
"$invalid": false,
"$name": "name",
"$error": {
"required": false, //这里是true代表有error , valid fail
"minlength": false
},
"$$validityState": {} //私有属性不详
}

$parsers, $formatters 是数据拦截

每一次view to scope 时,会触发$parsers里所有的方法, 我们可以在方法中对数据做一些处理,比如验证或者装换. $formatters 则是 scope to view 时触发

$viewChangeListeners 官网的说明是

Array of functions to execute whenever the view value has changed. 每一次view value change 触发

It is called with no arguments, and its return value is ignored. //no para , no return

This can be used in place of additional $watches against the model value. //用途不是很明白

$dirty , $valid 等,都是配合表单使用的,表单会对这个值总一些统计的工作。

还有一些方法 :

"$render",  
"$isEmpty",
"$setValidity", //常用的应该是这个, para(验证指令, isValid) 
"$setPristine",
"$setViewValue"

$render 和 $setViewValue 是我们做控件时一定要厉害的。

$render 是一个被angular调用的方法,由我们来告诉angular如何渲染页面。

当 digest 发现scope value changed , angular 会把 $modelValue 经过 $formatters 得出来的值放入 $viewValue中,(这时 $viewValue = $modelValue 经过 $formatters) 然后触发我们写好的 $render .

所以我们在 $render 里面就获取 $viewValue 来写入dom .

$setViewValue 则相反,它是angular写好的方法,我们来调用它,当dom 触发change 或 blur 等事件时,我们获取了value, 我们就调用这个 $setViewValue .

第一步 angular 会 $viewValue = newValue, 然后把经过 $parsers 得到的值 写入 $modelValue 和 scope value .

外传 :

题外话 , 框架和库的区别,库里有很多别人的方法,我们负责写过程,间中调用库里的方法 。框架呢则相反,我们写很多方法告诉,过程则是框架定义好的,它在执行过程时会调用我们写的方法。(忘记从哪里看到的,这让我领悟很多,特别分享一下).

$setValidity 是用于和表单验证通讯的 .

这里给一个自定义验证指令的例子

    <div ng-app="app" ng-controller="email">
<div ng-form="emailForm">
<input type="text" name="email" ng-model="email" is-abc />
<span ng-click="see()">{{ emailForm.$valid }}</span>
</div>
</div> angular.module("app", []).
directive("isAbc", ["$timeout", function ($timeout) {
return {
restrict: "A",
require: "ngModel",
link: function ($scope, $element, $attrs, $ctrl) {
var validator = function (v) {
$timeout.cancel($ctrl.timeout);
$ctrl.timeout = $timeout(function () {
if (v == "abc") {
$ctrl.$setValidity('isAbc', true);
return v;
} else {
$ctrl.$setValidity('isAbc', false);
return undefined;
}
}, 2000);
}
$ctrl.$parsers.push(validator);
}
}
}]);

这里我们创建了一个 is-abc 指令,我们拦截了ngModel,添加了验证手法,通过 $setValidity 通知 form , 这里还做了一个延迟验证的手法。

ng-form || form 指令

ng-form 和 form 是一样的,controller 名字是 form

    <div ng-app="app" ng-controller="email">
<form name="emailForm">
<input type="text" name="email" ng-model="email" required />
<input type="text" name="name" ng-model="email" required ng-minlength="2" />
<span ng-click="see()">{{ emailForm.$valid }}</span>
</form>
</div>

form 有一些规范,一定要有name , 里面的控件也都要有 name , 最好都用ng-model沟通,因为angular封装了自动添加controller 等等的事儿 .

流程大致上是这样,

form -> model -> 验证指令

指令通过拦截model做验证等,通过model告知form

form controller 有一些属性

                     var formController = {
"$name": "emailForm",
"$dirty": false, //form被动过
"$pristine": true, //form没人动过
"$valid": false, //全部验证pass
"$invalid": true, //有fail的
"email": {}, //key是form里头的控件nama,value是 控件 ngModel controller 对象,
"$error": {"required" : []} //key 是 error 指令名字,value是一个数组,里面是invalid控件的 ngModel controller对象
}

主要是收录了表单内控件的 ng-model controller 引用

form 中的方法

"$addControl", //添加ngModel controller ,ngModel会自动添加,除非自定义指令或许会用上
"$removeControl",
"$setValidity",  para(验证指令, isValid, ngModel controller) set ngModel的valid 
"$setDirty", no para , set属性
"$setPristine" no para , set属性

调用angular 提供的方法,它们会让form model parent等串联起来 .

更新 : 2015-05-23

在1.3版本后我们对 ngModel 的验证比较轻松了,ngModel.$asyncValidators or ngModel.Validators 来输入我们要的验证方法.

ngModel 嵌套的情况,有时候可能指令会嵌套,导致ngModel也嵌套了,有些人可能会直接这样写

scope : {

  ngModel : "="

}

表面上你看这样只是没有问题的,因为angular确实会帮你同步这个值,但是这样写的话,父层的$parsers是不会被触发的。

正确的做法是在子层通过 $render 和 $setViewValue 来修改父层的 ngModel

form 和 ngModel的更多相关文章

  1. angular4 Form表单相关

    ng4中,有两种方式去声明一个表单 一:Template-Driven Forms - 模板驱动式表单   [引入FormsModule] 1.ngForm赋值 [可以方便的获取表单的值] <f ...

  2. 理解AngularJS生命周期:利用ng-repeat动态解析自定义directive

    ng-repeat是AngularJS中一个非常重要和有意思的directive,常见的用法之一是将某种自定义directive和ng-repeat一起使用,循环地来渲染开发者所需要的组件.比如现在有 ...

  3. 【AngularJs】---$sce 输出Html

    [问题描述] angular js的强大之处之一就是他的数据双向绑定功能----->ng-bind和针对form的ng-model 但在我们的项目当中会遇到这样的情况,后台返回的数据中带有各种各 ...

  4. Angular JS API

    ng function angular.bind angular.bootstrap angular.copy angular.element angular.equals angular.exten ...

  5. angular中的ng-bind-html指令和$sce服务

    angular js的强大之处之一就是他的数据双向绑定这一牛B功能,我们会常常用到的两个东西就是ng-bind和针对form的ng-model.但在我们的项目当中会遇到这样的情况,后台返回的数据中带有 ...

  6. angularJS 系列(一)

    angularJS 中 $scope 的原型 和 原型继承之间的细微差别是什么? 参考:http://stackoverflow.com/questions/14049480/what-are-the ...

  7. 从浅入深剖析angular表单验证

    最近手上维护的组件剩下的BUG都是表单验证,而且公司的表单验证那块代码经历的几代人,里面的逻辑开始变得不清晰,而且代码结构不是很angular. 是很有必要深入了解表单验证. 入门之前,我觉得应该先了 ...

  8. AngularJs的基本使用(一)

    AngularJS 指令 AngularJS 通过 ng-directives 扩展了 HTML,AngularJS 指令是以 ng 作为前缀的 HTML 属性. ng-app 指令定义一个 Angu ...

  9. angular的小实例

    主要是使用了angular的指令. 学习地址:http://www.runoob.com/angularjs/angularjs-tutorial.html 1. 效果: 输入数据剩余字数会相应减少, ...

随机推荐

  1. 2014-07-23 .NET实现微信公众号接入

    今天是在吾索实习的第11天.今天我跟我的实习小组的组员们,解决了关于使用ASP.NET进行微信公众号接入的问题.因为我们小组成员也是刚接触微信公众号的二次开发,所以在解决该问题的工程中也走了不少弯路. ...

  2. css实现居中的各种方法

    css垂直居中有很多种方法,可以参考下这个网站

  3. python游戏编程——跟13岁儿童学编程

    python爬虫基本告一段落,琢磨搞点其他的,正好在网上看到一个帖子,一个外国13岁小朋友用python写的下棋程序,内容详细,也有意思,拿来练手. 13岁啊.. 我这年纪还在敲 dir啥的吧 想到原 ...

  4. delphi算法

    /  求余 mod 取模 var a1,a2,a3 : Integer; b1,b2,b3 : Integer; c1,c2 : Integer;begin a1 := 987; //ShowMess ...

  5. webpack之基础学习

    webpack工作原理: 通过一个入口文件,main.js开始找到你的项目的所有依赖文件,使用loaders处理它们,最后打包为一个浏览器可识别的JavaScript文件. Webpack的核心原理 ...

  6. pods 这两篇就够了

    http://www.cnblogs.com/gongyuhonglou/p/5801681.html http://blog.csdn.net/iunion/article/details/1701 ...

  7. C++编程规范之17:避免使用“魔数”

    摘要: 程序设计并非魔术,所以不要故弄玄虚,要避免在代码中使用诸如42和3.1415926这样的文字常量.它们本身没有提供任何说明,并且因为增加了难于检测的重复而使维护更加复杂.可以用符号名称和表达式 ...

  8. SQL Server error "Xml data type is not supported in distributed queries" and workaround for it

    Recently while working with data migration,got an error while running a following query where Server ...

  9. Nyoj 43 24 Point game 【DFS】

    24 Point game 时间限制:3000 ms  |  内存限制:65535 KB 难度:5 描写叙述 There is a game which is called 24 Point game ...

  10. (3)选择元素——(15)总结(Summary)

    With the techniques that we have covered in this chapter, we should now be able to locate sets of el ...