如何优雅的使用 Angular 表单验证

随便说说,这一节能够跳过

去年参加 ngChine 2018 杭州开发者大会的时候记得有人问我: Worktile 是何时开始使用 Angular 的,我说是今年(2018年) 3 月份开始在新模块中使用最新的 Angular 6,他说是否是有点晚了,我当时愣了一下。 其实仔细回想了一下, Angular 2.0 正式发布也就在 2016-09-14 号,因此也就晚了 1 年多一点点才开始使用而已嘛,再加上 2.0 到 4.0 的过渡或多或少仍是有一点点坑的,不是很稳定,此时投入不是特别合适,虽然升级简单,可是仍是有不少概念和API须要从新学习,好比 HttpClient,路由等等(在 2.0 的时候咱们是有尝试在边缘的一个 Open API Doc 文档站点使用过的,咱们一直在关注着最新的 Angular)html

因此我以为 4.0 (也就是 2017-03)以后的 Angular 才真真正正的开始趋于稳定,能够开始尝试学习和使用,再加上通过了 1 年多的社区实践,踩坑,基础生态建设,我以为今年(2018年)才是企业大规模尝试使用 Angular 最佳时间点,再加上 Angular CLI 以及 @angular/cdk的逐渐强大, 我想说这是一个最好的时代。前端

另外还有一个缘由是 2016 - 2017 年属于我司最艰难的困难时期,压根没有心思考虑切换最新技术栈,因此那 2 年基本上属于埋头作业务。react

如今回过头来看 Angular ,在前端框架高速发展的那几年,由于正式版发布迟迟延期,致使市场被后起之秀 React, Vue 等优秀框架占有,好在新的 Angular 足够优秀,足够前瞻,值得花更多的时间投入学习和使用,如今还不算晚。因此慢有必定道理的,由于须要精雕玉琢,衡量将来的趋势等等,可是从完美支持 TypeScript,RxJS 这 2 点来讲,Angular 的确走在了前面。git

回归正题,说到表单,我认为一个强大表单应该包含下面3部分功能

1.收集用户的输入的表单数据,在 Angular 中经过 ngModel 实现双向绑定很是方便;程序员

2.经过各类验证器验证表单元素输入的数据是否合法,Angular 内置了经常使用的验证器(required、pattern、email,min,max,minLength,maxLength);github

3.验证后给予用户反馈,好比验证不经过给予错误的提示信息。前端框架

我以为 Angular 的表单无疑是三大框架中最强大的,没有之一,并且是官方原生提供支持和维护,提到 Angular 的表单确定要说下 Angular.js 的表单,其实 Angular 的表单基本上继承了 Angular.js 表单的全部功能,同时比 Angular.js 更强大,API 更友好。antd

另外说下本文不是普及 Angular Form 表单的基本知识的,若是有不了解的能够看 angular forms guide ,由于官方文档已经写的特别好了。框架

那么 Angular 的表单和 Angular.js 相比到底有哪些改进呢?

自定义 ngModel

在 Angular.js 中 ng-model 只能用于 input,select 等内置的 HTML 表单元素,若是是一个自定义的 select 框(div),可能就没法使用自带的 required 等验证器了异步

可是能够经过猥琐的方式处理,好比加一个隐藏的原生 HTML 表单元素,这个元素上绑定的 ng-model 和自定义的 select 框的 model 是同样的,而后经过这个隐藏元素是否验证经过去控制自定义 Select 的验证样式

那么在 Angular 中能够很方便让任何自定义的组件使用 ngModel 和 内置的验证器,只要你的自定义组件实现 ControlValueAccessor 接口,同时在组件的 providers 中加上 NGVALUEACCESSOR 的 provider 便可,具体如何实现一个自定义的支持 ngModel 组件自行搜索下,官方文档好像没有找到相关介绍, 附一个 stackoverflow question

结构型指令内部的表单元素自动识别

在 Angular.js 中若是有 ng-if 之类的动态指令,内部的表单元素不会自动追加到 Form 上,必须经过扩展一个自定义指令 dynamicFormControl 去手动追加到 ngForm 上,可是在 Angular 中不须要用户本身去处理,只要元素被渲染,会自动附加到 ngForm Controls 中。

响应式表单

Angular 中除了模板驱动表单外,还新增了响应式表单,让用户多了一份选择,在某些复杂的场景下,响应式表单会更有优点。

动态表单支持更好

在 Angular 中不论是模板驱动表单仍是响应式表单,对于动态建立表单的支持都很好,能够轻松的经过 [attr.name]="formName"[name]="formName" 实现动态表单元素的建立。若是有复杂的验证器,那么使用 响应式表单 会更好。

模板驱动表单验证器支持属性绑定,动态控制是否须要验证

若是一个表单元素(好比说用户名)是否为必填不是肯定的,而是动态设置的, 在 Angular 中能够经过属性绑定 [required]="isRequired" 很是方便的控制,我看了下 Angular.js 的源码如今也是支持的,不知道是我之前没有发现呢仍是以后的版本加上的功能。

支持异步验证器

若是要验证用户名输入是否已经存在,就须要请求 API 远程验证,那么这个验证就是一个异步,若是验证不支持就会致使验证结果没有返回的时候就直接提交表单了。若是支持异步会更加的完善。

经过上述的几点来看, Angular 表单基本已经完美了,可是

咱们还须要让验证错误提示更加简单

回头再看下开头的介绍的表单应该包含下面3部分功能:

1. 收集用户的输入的表单数据; 这个基本上 ngModel 双向绑定的语法糖已经简化的不能再简化了,固然使用响应式表单连 ngModel 也能够不写;

2. 内置的验证器知足大部分场景,可是仍是会有不少经常使用的验证器官方没有提供,好比 重复验证,远程惟一性验证等等,@Nightapes/ngx-validators@gangachris/ng-validators 这2个第三方库扩展了不少,即便不知足本身扩展也很简单;

3. 验证后给予用户反馈,验证不经过给予错误的提示信息。对于这个错误提示信息,每一个产品每一个用户都会有不同的需求,Angular 把能够作到的都作到了,都自动追加了 ng-invalidng-validng-touched 等 class,还有就是哪些元素哪一个验证器验证失败均可以从 ngModel 和 ngForm 方便的获取到,错误提示只能交给用户本身去处理。

对于验证错误提示,手动写错误提示的模版会很啰嗦,写模版自己也没什么,怕就怕哪天设计师改需求了,原有的提示方式换了一个新的方式,那整个系统都须要挨个替换,有追求的程序员最怕的就是作重复没有含量的工做,并且有时候还没法经过批量替换完成,因此在使用 Angular.js 1.x 的时候我就封装了一个表单验证库 angular-w5c-validator,刚开始发布的时候功能比较简单,后来有人提各类 Issue,逐渐改善,我以为这个验证库对于不少人来讲仍是有帮助的,至少我以为是更优雅的处理了各类错误提示,star 很少,可是证实了这个封装仍是有必定价值的。

那么咱们即便如今升级到了 Angular ,也面临着错误提示如何处理的问题,固然也有些类库处理了相关问题,可是好像都没有找到特别好用的。

1.ngx-errors 仍是手写模版,只是简化了写法。

2.ng-zorro-antd 组件库关于表单组件对错误验证提示也作了不少工做,可是仍是须要手写模版配置。

既然没有相关的类库符合咱们的需求,那么显然就须要本身造轮子,因此咱们去年在升级 Angular 时就按照咱们的方式在组件库的 Form 表单模块加上了和 Angular.js angular-w5c-validator 相似的 API,得益于 Angular 框架的优秀,造起轮子特别简单。

内部的组件库暂时还没法开源出去让更多人使用,可是的可是

ngx-validator 已经能够开始使用了

因此这周我单独抽离了表单验证功能为一个独立的组件 ngx-validator , 若是你也再为表单验证错误提示苦恼,也在寻找一种更优雅的错误处理方式,但愿个人这个库能够帮助到你或者给你一个启发。

ngx-validator Demo 示例,点击直接查看演示

ngx-validator.gif

最后的最后感谢你耐心阅读到此,这篇博客已经计划了 3 个多月了,由于工做繁忙一直没有时间,这周末下了一个狠心,必须完成!已经被儿子打扰屡次,还有就是 ngx-validator 目前基本的功能已经完成,后期还有不少加强的验证器,测试须要补充,还不是特别完善,欢迎你们提宝贵意见。

 

本文做者:徐海峰

文章来源:Worktile技术博客

欢迎访问交流更多关于技术及协做的问题。

文章转载请注明出处。

相关文章
相关标签/搜索