nghover如何使用用 AngularJS 的 ngShow 和 ngHide

form)和新的消息提示模块(ngMessages)1.3中嘚form表单变得空前强大。

下面让我们一起来领略这些惊人的表单新特性吧

本文首次发表于2014年9月2日,最近修改于2014年9月4日

2、演讲视频,Github仓库囷演示应用3、基础知识4、HTML5验证器和解析错误5、验证器管道($validators pipeline)6、通过异步验证器实现异步验证7、错误消息渲染8、控制何时更新数据模型(model)9、动态苼成表单元素10、关于解析器和格式化11、正在进行中的工作

表单验证在任何一个框架中都是一只晋安驯服的野兽在Vanilla JS中就更加让人捉摸不透。虽然已经有一些在制定中的HTML5表单验证API但是这些API是不一致的,同时不失所有设备都很好的支持甚至一些平台根本就不支持它们。

幸亏AngularJs通过ngModel对表单验证做了一个多功能的包装如果需要的话ngModel的内部验证也可以只使用HTML5验证API,当然ngModel总体上的跨浏览器的统一性还是非常不错的AngularJs 1.3對表单的控制能力远远高于1.2版本。

不过还有好多知识点需要理解的让我们快点开始吧……

演讲视频,Github仓库和演示应用

不是很久以前那昰在2014年6月多伦多的AngularJs交流会上,我讲述了AngularJs的表单验证几乎涵盖了这篇文章的所有话题。视频放在Youtube上链接在下面。请记住在当时异步验證API还不稳定。所以当视频中讨论API对于基于promise的验证是如何工作的时候请查看一下本文章的后面部分。除此好好欣赏视频吧,期望你能喜歡我潇洒的幽默

视频传送门[Youtube视频,要爬长城才能看到的额]:

有一个朋友的示范仓库展示了本文列出的所有特性在线示范和仓库地址如丅:

我们不能假想所有的人都了解Angular的表单是nghover如何使用用的,所以在开始之前先简要的介绍一下nghover如何使用用

用户angular的人就会知道,ng-model属性总是位于输入元素上如(input, select, textarea)。这个强大的指令连接中DOM种输入元素的输入值(称为“view value”)和对应作用域(scope)中的数据模型值(称为“model value”),即当鼡户输入时输入值(view value)改变,对应的数据模型值(model value)也会相应更新反之亦然。

 

现在当用户再input元素上输入值的时候scope中的对应数据模型會同步此值。当按钮被按下的时候scope中的myName属性值会变化,然后input输入域会显示这个值(‘defaut value’)

这种机制的好处是我们不用写任何js代码就可鉯完成一些标准的处理流程,如传递数据给scope执行验证器,触发数据模型绑定的事件看一下下面的代码:

 

上面的input元素通过ng-model指令绑定了一個scope中的myEmail属性。用户输入数据时将自动修改scope上的myEmail属性值为输入值同时input元素上还定义了一系列的验证器来验证用户的输入,只有当用户输入嘚值满足所有定义验证器的条件这个输入值才会被angualr写入到scope中绑定的属性上。上面例子中ngModelController将会检查:

* 输入值须是一个合法的邮箱地址(type="email")

通过这四个验证器我们不用写一行js代码就可完成表单验证,同时可以在不同的表单元素上复用

当一个验证器验证失败的时候,将会把錯误信息注册到ngModelController实例中的$error对象中不过要想展示错误信息的话,我们首先需要能在模板(html)中访问这个ngModelController 的model此处可以把输入元素用一个form元素包裹,同时给form元素和input元素写上自己的name属性和值

 

现在我们可以在模板中通过myForm.myEmail.$error检查此input元素的验证状态,同时还可以检查表单元素的其他状態属性如$pristine(未被修改过为true), $dirty(修改过为true), $valid(通过验证), $invalid(未通过验证)。通过这些值我们可以在模板中定义何时显示错误信息

 

我们可以创建自定义嘚ngModel组件指令来访问ngModelController实例并实现验证器,所有要做的仅仅是在指令定义时通过require属性来注入ngModel的控制器这种方式创建的指令需要和ngModel一起使用。

 

formえ素拥有自己的控制器form的控制器是为了管理整个表单验证而添加的,它拥有$valid和$invalid属性下面的例子是一个根据表单是否通过验证的状态来決定是否把数据提交到后台的表单控制器。

 

在form的html模板中通过ng-submit属性指定表单提交时调用控制器中的submit方法

 

不知你是否注意都我们使用了一个data集合来存储所有的表单数据模型。如果我们仅仅且把所有的表单数据模型存储在一个集合中那么在提交表单时可以直接把这个集合提交給后台。这种模式为我们省去不少的js代码

希望上面的介绍是你初略的了解了ngModel的一些基本知识。接下来我们开始介绍AngualrJs 1.3中的那些新特性

HTML5验證器和解析错误

现在所有的HTMl5验证器都被绑定到ngModel上,当错误发生时错误信息将作为属性挂在ngModel.$error上。下面的表格展示了属性名和错误错误类型嘚对应关系

下面的input元素的type类型也会注册验证器。

ngModel如何处理这些错误

由于HTML5自身带有的表单验证特性一些类型的input输入框只有当输入值满足驗证条件后才会生效(也就是element.value只能取到通过验证的输入值)。

在1.3中ngModel将先处理解析相关的验证,然后才是其它的验证也就是说会先判断┅个值是否是符合number, date, url和email这种类型验证,然后才是其它的如required, minlength, max等等

在AngularJs 1.3中我们使用$validators来代替以前的$parsers和$formatters实现表单验证。为了将自定义验证器注册到表單验证器中(ngModel.$validators)我们需要先创建包含ngModel的自定义指令。下面的例子展示了如何通过$validators定义一个判断密码输入是否符合要求的验证器

 

当在控淛器管道(给$validators添加属性)注册验证器时需要函数返回一个布尔类型的值。

对应的HTML代码如下

 

通过异步验证器实现异步验证

下面让我们用同样嘚方式来创建一异步验证器功能的指令通过ajax与后台交互的结果来判断输入的用户名是否可用。

 

异步验证器($asyncValidators)在触发的时候需要每个验证器返回一个promise对象当这个promise完成的时候表示验证通过,拒绝(reject)的时候将把验证的错误信息注册到对应的$error对象上只有当所有的验证器(包含異步验证器)验证通过后,值才会被写入scope中

需要记住的是,异步验证器只有再其他验证器全部验证通过后才会触发这种机制有效的防圵了在用户名无效时发送无意义的后端验证请求。下面的样例代码很好的诠释了这点

 

当一个或多个异步验证器正在验证中时,对应model和form的$valid囷$invalid标志都被置为undefined只有当所有的异步验证器完成后,$valid和$invalid才会根据所有验证器验证的结果来赋值(true or false)在这个期间,在modal和form上会有一个特殊的标志$pending(徝为true)来标识当所有异步验证完成后这个值将被移除。

因此通过$pending标志我们可以在正在执行异步验证的input旁边加上“加载中动画”,正如上媔的用户名的异步验证可以修改如下。

 

Angular会默认展示模板中定义的所有错误提示我们有很多方式来优化这种提示。

一个input输入域在聚焦(focus)再夨去焦点(blur)后它的$touched属性都会是true。所以我们可以使用ngIf或者ngShow指令根据$touched的值来控制错误信息何时显示

 

但是思考一下如果我们没有聚焦到任何一個输入域就直接提交表单呢,是不是也应该展示所有错误信息我们可以增加一个对myForm.$submitted属性的判断来修复这个bug。

 

现在这个表单就变得更加友恏了但是当错误信息太多了回发生什么?我们应该如何控制错误信息展示的时机和行为如何给这些错误提示给一个优先级使得每次只顯示一条错误提示?AngularJs 1.3通过一个新的ngMessages模块提供了这些功能

下面使用ngMessages来显示错误信息。

 

使用ng-messages最多只会有一条错误信息会被展示并且ng-messages指令会按照html模板中的顺序渲染第一条匹配的错误提示。注意到此处我们仍然使用了前面的ng-if属性来控制错误信息块是否显示

为了能够再项目中使鼡ngMessage,我们需要下载并引入angular-messages.js文件并将它作为我们应用的一个依赖注入。

 

控制何时更新数据模型(model)

AngularJs 1.3中添加了一个新的ngModelOptions属性通过对该属性的配置可以控制input元素上的ngModel何时更新。一个典型的应用就是防止值抖动(value debouncing)通过这个属性可以让数据模型值(model value)只有在特定事件发生时才更新。以往默認的行为是每次字符输入都会更新数据模型值

下面的例子展示的是只有在用户停止输入500毫秒后(500ms内不得再输入,否则重新计时)才出发绑定嘚所有验证器

 

同时可以通过设置blur属性值为0使得当输入域失去焦点时立即触发验证。

另一个应用场景是根据用户输入的搜索字符串来改变當前页面的url地址的时候可以观看前面的视频作详细了解。

引入ng-if是因为它能很容易的添加和移除form的子区域如此可以很好地控制表单中可選区域的添加和移除。想象一下如何编写一个只有在用户想要提供邮箱地址时候才展示邮箱收集输入框的form表单

 

上面代码的核心点就是邮箱输入框只会在checkbox为true时候被添加。由于这个输入域是根据状态添加到DOM中和从DOM中移除的所以它的添加和移除会直接影响到整个form的验证状态。

洳果我们现在需要不止一个邮箱输入框那么我们该如何重构我们的HTML代码呢(保证表单的验证和错误提示方式与前面一致,每个输入域【input】囷form都有自己的提示和验证)我们可以使用ng-repeat指令生成需要的输入域并绑定数据模型。

 

上面的代码当某一个邮箱输入错误时会发生什么呢我們如何知道是哪一个输入框错误呢?如何给错误的输入框给出单独的错误提示呢解决方法是使用ng-form指令给重复元素创建嵌套的表单域。

 

牛逼啊!等等…这满屏的错误提示你玩我呢我只想对循环生成的同类型的邮箱地址验证给出一个总的提示就够了!绝对事儿逼啊…满足你,我们再在循环块的包含块上增加一个ng-form指令就行啦…233…就是这么叼…

 

一个好的使用例子是用于处理时间相关的输入元素如date, time, datetime, week, month等等。下面的實例中的显示值是一个字符串而对应的模型值却是一个Date实例。来来来上代码。

 

$formatters是$parsers的逆过程所以我们需要向下面这样把一个Date实例的模型值格式化成对应的字符串展示。

 

因此$parsers和$formatters总是成对工作的只有这样才能使得值在两种不同的类型或者要求下正确转换。

ngModel在AngularJs最初版本就已經存在到现在1.3版本中的新特性极大的提升了开发者和使用者的体验。虽然现在新特性可能还有一两处不恰当的地方但这些不足将在1.3的穩定版本中被修改。但现在你可以放心大胆的用RC0发布版中的新特性因为所有API已经冻结,不会再做修改所以勇敢向前吧,骚年…不要害羞:)

如果你发现有bug或者有任何想法,欢迎到AngularJs的github仓库创建issue记得在issue描述中@ matsko额。这样我才能能快速的看到您的反馈并响应

非常感谢您阅读本篇文章。欢迎分享本文并在Twitter上关注


}

我要回帖

更多关于 eve ng 使用教程 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信