如何优雅的使用 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)
所以我觉得 4.0 (也就是 2017-03)之后的 Angular 才真真正正的开始趋于稳定,可以开始尝试学习和使用,再加上经过了 1 年多的社区实践,踩坑,基础生态建设,我觉得今年(2018年)才是企业大规模尝试使用 Angular 最佳时间点,再加上 Angular CLI 以及 @angular/cdk的逐渐强大, 我想说这是一个最好的时代。
另外还有一个原因是 2016 - 2017 年属于我司最艰难的困难时期,压根没有心思考虑切换最新技术栈,所以那 2 年基本上属于埋头做业务。
现在回过头来看 Angular ,在前端框架高速发展的那几年,因为正式版发布迟迟延期,导致市场被后起之秀 React, Vue 等优秀框架占有,好在新的 Angular 足够优秀,足够前瞻,值得花更多的时间投入学习和使用,现在还不算晚。所以慢有一定道理的,因为需要精雕玉琢,衡量未来的趋势等等,但是从完美支持 TypeScript,RxJS 这 2 点来说,Angular 的确走在了前面。
回归正题,说到表单,我认为一个强大表单应该包含下面3部分功能
1.收集用户的输入的表单数据,在 Angular 中通过 ngModel 实现双向绑定非常方便;
2.通过各种验证器验证表单元素输入的数据是否合法,Angular 内置了常用的验证器(required、pattern、email,min,max,minLength,maxLength);
3.验证后给予用户反馈,比如验证不通过给予错误的提示信息。
我觉得 Angular 的表单无疑是三大框架中最强大的,没有之一,而且是官方原生提供支持和维护,提到 Angular 的表单肯定要说下 Angular.js 的表单,其实 Angular 的表单基本上继承了 Angular.js 表单的所有功能,同时比 Angular.js 更强大,API 更友好。
另外说下本文不是普及 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-invalid
、ng-valid
、ng-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 示例,点击直接查看演示
最后的最后感谢你耐心阅读到此,这篇博客已经计划了 3 个多月了,因为工作繁忙一直没有时间,这周末下了一个狠心,必须完成!已经被儿子打扰多次,还有就是 ngx-validator
目前基本的功能已经完成,后期还有很多增强的验证器,测试需要补充,还不是特别完善,欢迎大家提宝贵意见。
本文作者:徐海峰
文章来源:Worktile技术博客
欢迎访问交流更多关于技术及协作的问题。
文章转载请注明出处。
如何优雅的使用 Angular 表单验证的更多相关文章
- Angular 表单验证类库 ngx-validator 1.0 正式发布
背景介绍 之前写了一篇 <如何优雅的使用 Angular 表单验证>,结尾处介绍了统一验证反馈的类库 ngx-validator ,由于这段时间一直在新模块做微前端以及相关业务组件库, ...
- Angular表单验证
novalidate 去掉html5自带的验证 ng-minlength 规定输入文本的最小长度 ng-maxlength 规定输入文本的最大长度 ng-submit 接收一个方法名 ...
- 简单的angular表单验证指令
<html ng-app="myApp"> <head> <meta charset="UTF-8"> <title& ...
- angular表单验证实例----可用的代码
前段时间,公司做一个单页面,就是一个表单验证,早开始在菜鸟教程上关注了angular,所以下派上用场了 angular里面对于表单验证,设置了很多指令. 也就是说不用自己写一些逻辑,直接绑定指令就行. ...
- 从浅入深剖析angular表单验证
最近手上维护的组件剩下的BUG都是表单验证,而且公司的表单验证那块代码经历的几代人,里面的逻辑开始变得不清晰,而且代码结构不是很angular. 是很有必要深入了解表单验证. 入门之前,我觉得应该先了 ...
- angular 表单验证
最近在用angular写表单验证时 , 不小心把ng-model全替换删掉了, 然后发现之前写的验证都失效, 在查阅资料和反复修改摸索后, 发现angular中的表单验证, 都是基于ng-model的 ...
- 简话Angular 05 Angular表单验证
一句话: 可以使用所有html5表单验证功能,同时Angular还增强了部分验证,支持动态验证 1. 上源码 <div ng-controller="ExampleController ...
- Angular 表单验证 基础篇
<div class="nav"> <h4>表单验证</h4> <form ng-app="myApp" name=& ...
- ngVerify - 更高效的 angular 表单验证
ngVerify v1.5.0 a easy Angular Form Validation plugin.简洁高效的__angular表单验证插件__ See how powerful it.看看它 ...
随机推荐
- 2019-3-26WinForm窗体间如何传值的几种方法
窗体间传递数据,无论是父窗体操作子窗体,还是子窗体操作符窗体,有以下几种方式: 公共静态变量: 使用共有属性: 使用委托与事件: 通过构造函数把主窗体传递到从窗体中: 一.通过静态变量 特点:传值是双 ...
- PHP 关于判断输入日期是否合法
合法要求 一年仅十二个月 4,6,9,11月仅30天,1,3,5,7,8,10,12月仅31天 闰年2月29天,否则28天 输入的变量年,月,日为数字 代码: <?php //PHP中判断输入的 ...
- 免费获取SSL证书/一键安装SSL证书/https加密
因为我用的是恒创的香港服务器 虽然价格相较于大促的阿里云贵一些,但是有一个有点不用备案... 安装步骤: 1.登录云主机控制面板, 在 其他管理 中找到并进入 SSL证书 设置. 注意:如拥有多个域名 ...
- 数据分析——matplotlib
基础 # coding=utf-8 import matplotlib.pyplot as pt import numpy as np from matplotlib import font_mana ...
- VB.NET或C#报错:You must hava a license to use this ActiveX control.
VB.NET或者C# winform开发时,如果使用了Microsoft Visual Basic 6.0 ActiveX,并动态创建该控件实例,那么程序移植到没有安装Visual Basic 6.0 ...
- Java 基础 JRE和JDK的区别
JRE(Java Runtime Environment,Java运行时环境)是Java程序运行所需的软件环境,包含Java虚拟机和Java基础类库. JDK(Java Development Kit ...
- 10-HTTPServletReauest和HTTPServletResponse
Servlet配置方式 1. 全路径匹配 以 / 开始 /a /aa/bb localhost:8080/项目名称/aa/bb 2. 路径匹配 , 前半段匹配 以 / 开始 , 但是以 * 结束 /a ...
- 上传插件webupload之调用拍照兼容问题
在项目中,移动端用到了webupload插件来实现上传功能(我觉得这个插件挺好用的,所以无论pc还是移动端我都使用了这个插件来做上传功能) 在移动端要调起拍照功能,实现上传,须得在webuploade ...
- JavaScript字符串与数组方法整理
字符串(String)的方法: 代码后面的都是返回值 var str = "atusdgafsvg"; var str1 = "123456789"; var ...
- angular.isUndefined()
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...