form 和 ngModel
参考
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的更多相关文章
- angular4 Form表单相关
ng4中,有两种方式去声明一个表单 一:Template-Driven Forms - 模板驱动式表单 [引入FormsModule] 1.ngForm赋值 [可以方便的获取表单的值] <f ...
- 理解AngularJS生命周期:利用ng-repeat动态解析自定义directive
ng-repeat是AngularJS中一个非常重要和有意思的directive,常见的用法之一是将某种自定义directive和ng-repeat一起使用,循环地来渲染开发者所需要的组件.比如现在有 ...
- 【AngularJs】---$sce 输出Html
[问题描述] angular js的强大之处之一就是他的数据双向绑定功能----->ng-bind和针对form的ng-model 但在我们的项目当中会遇到这样的情况,后台返回的数据中带有各种各 ...
- Angular JS API
ng function angular.bind angular.bootstrap angular.copy angular.element angular.equals angular.exten ...
- angular中的ng-bind-html指令和$sce服务
angular js的强大之处之一就是他的数据双向绑定这一牛B功能,我们会常常用到的两个东西就是ng-bind和针对form的ng-model.但在我们的项目当中会遇到这样的情况,后台返回的数据中带有 ...
- angularJS 系列(一)
angularJS 中 $scope 的原型 和 原型继承之间的细微差别是什么? 参考:http://stackoverflow.com/questions/14049480/what-are-the ...
- 从浅入深剖析angular表单验证
最近手上维护的组件剩下的BUG都是表单验证,而且公司的表单验证那块代码经历的几代人,里面的逻辑开始变得不清晰,而且代码结构不是很angular. 是很有必要深入了解表单验证. 入门之前,我觉得应该先了 ...
- AngularJs的基本使用(一)
AngularJS 指令 AngularJS 通过 ng-directives 扩展了 HTML,AngularJS 指令是以 ng 作为前缀的 HTML 属性. ng-app 指令定义一个 Angu ...
- angular的小实例
主要是使用了angular的指令. 学习地址:http://www.runoob.com/angularjs/angularjs-tutorial.html 1. 效果: 输入数据剩余字数会相应减少, ...
随机推荐
- 普通的101键盘在Mac上的键位对应
为了方便,搞了一个普通的101有线全键盘 + Magic TrackPad配Macbook. 然后发现了一个小问题,按键对应似乎不像我想的那么完美,F1~F12和Macbook不对应,于 ...
- CPU天梯图
一幅图,了解CPU
- iOS项目更新之升级Xcode7 & iOS9
金田 前言 Apple 的WWDC所发布内容在给大家带来惊喜之际,给各位iOS开发的同仁却也带来了不同程度的麻烦.首先不讲新功能,就单指原来老版本的项目升级.代码升级,就是一堆问题,而且是不 ...
- cocos2d-x 找不到资源文件问题
问题描述: 在项目中引用到了图片,但是运行时报错: Unhandled exception at 0x001049DE in hello.exe: 0xC0000005: Access violati ...
- 黑马程序员_Java其他对象(System,Runtime,Date,Calendar,Marh-Random)
System System类包含一些有用的类字段和方法(都是静态的).它不能被实例化. 在System类提供的设施中,有标准输入.标准输出和错误输出流:对外部定义的属性和环境变量的访问:加载文件和库的 ...
- linux应用程序地址布局
Linux应用程序在内存中的布局,由高地址到低地址依次为:栈.堆.BSS段.数据段.代码段.代码段的起始地址固定为0x8048000,无论哪一个应用程序它的代码段起始地址一定是0x8048000,这里 ...
- 高性能Web服务器Nginx及相关新技术的应用实践-张宴
http://files.cnblogs.com/files/niaowo/%E9%AB%98%E6%80%A7%E8%83%BDWeb%E6%9C%8D%E5%8A%A1%E5%99%A8Nginx ...
- Havel定理
先贴一个百度百科的注释 Havel定理编辑 本词条缺少概述.名片图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧! 中文名 Havel定理 外文名 Canisters theorem 特 ...
- split
import java.io.IOException; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; /** * 解析知网文章的页面 ...
- 视图的touch事件的传播控制
在视图控制器类中.self.view中会包含多个多层的自己定义视图. 我自己定义了一个uicollectionview类,名称为gridview,又自己定义了一个uicollectionviewcel ...