强大的 Angular 表单验证功能详细介绍


Posted in Javascript onMay 23, 2017

Angular 支持非常强大的内置表单验证,maxlength、minlength、required 以及 pattern。使用 Angular 的内置表单校验能够完成绝大多数的业务场景的校验需求,但有时我们还需要实现更为复杂的表单校验功能,这时可以使用 Angular 提供的表单自定义校验(Custom Validator)。下面,我们就来了解一下如何使用 Angular 的自定义表单校验

效果图:

强大的 Angular 表单验证功能详细介绍

1、首先,来创建我们的注册组件(register),并在模版中显示一个简单的表单

<h3 class="text-center">注册</h3>

<form>

 <div class="form-group">
 <label for="username">用户名:</label>
 <input type="text" id="username" class="form-control" >
 </div>

</form>

为了使表单看上去能够漂亮一些,在 index.html 中引入 bootstrap 样式文件:

<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

2、接下来确定我们的验证需求:

 我们希望用户名只能包含数字、字母和下划线,且不能以下划线开头

首先为 form 标签添加 formGroup 指令:

<form [formGroup]="registerForm" >

并且为 input 标签添加 formControlName 指令:

<input formControlName="username" type="text" id="username" class="form-control" >

3、在代码中定义验证规则:

从内置表单模块中导入以下类:

import { FormBuilder, FormGroup, Validators } from '@angular/forms';

其中:

      1. formBuilder 用来构建表单数据
      2. formGroup 表示表单类型
      3. Validators 包含了表单内置的验证规则,如: Validators.required

定义表单属性

registerForm: FormGroup;

定义表单验证不通过时每一项显示的错误消息(目前我们只有 username )

formErrors = {
 username: ''
 };

为每一项验证规则定义验证失败时的说明文字(表单控件可能有多条验证规则,由不通过的验证说明构成一条错误消息)

validationMessage = {
 'username': {
  'minlength': '用户名长度最少为3个字符',
  'maxlength': '用户名长度最多为10个字符',
  'required': '请填写用户名'
 }
 };

在构造函数中添加 fb 属性用来构建表单

constructor(private fb: FormBuilder) { }

添加构建表单的方法

buildForm(): void {
 // 通过 formBuilder构建表单
 this.registerForm = this.fb.group({
 /* 为 username 添加3项验证规则:
 * 1.必填, 2.最大长度为10, 3.最小长度为3
 * 其中第一个空字符串参数为表单的默认值
 */
 'username': [ '', [
  Validators.required,
  Validators.maxLength(10),
  Validators.minLength(3)
 ]]
 });

接下来我们添加一个方法用来更新错误信息

onValueChanged(data?: any) {
 // 如果表单不存在则返回
 if (!this.registerForm) return;
 // 获取当前的表单
 const form = this.registerForm;

 // 遍历错误消息对象
 for (const field in this.formErrors) {
  // 清空当前的错误消息
  this.formErrors[field] = '';
  // 获取当前表单的控件
  const control = form.get(field);

  // 当前表单存在此空间控件 && 此控件没有被修改 && 此控件验证不通过
  if (control && control.dirty && !control.valid) {
  // 获取验证不通过的控件名,为了获取更详细的不通过信息
  const messages = this.validationMessage[field];
  // 遍历当前控件的错误对象,获取到验证不通过的属性
  for (const key in control.errors) {
   // 把所有验证不通过项的说明文字拼接成错误消息
   this.formErrors[field] += messages[key] + '\n';
  }
  }
 }
 }

下面只需要在表单构建结束后初始化错误消息,并且在每次表单数据更改时更新错误消息就可以了

在 buildForm 方法中添加如下代码

// 每次表单数据发生变化的时候更新错误信息
 this.registerForm.valueChanges
 .subscribe(data => this.onValueChanged(data));

 // 初始化错误信息
 this.onValueChanged();

此时,我们已经很好的控制了错误信息,下面只需要在表单模版中添加错误信息的显示就可以了

在 input 标签下方添加如下代码:

<div *ngIf="formErrors.username" 
 class="showerr alert alert-danger" >{{ formErrors.username }}</div>

添加如下代码到表单模版的 css 中:

form {
 width: 90%;
 max-width: 45em;
 margin: auto;
 }

 .showerr {
 white-space: pre-wrap;
 }

现在我们就可以尝试运行了,在代码不报错的情况下已经能够看到非常好的效果了

如果代码报错或没有出现想象中的效果则可以参照本文结尾的完整代码进行修改

4、虽然我们已经搭建了整个布局,但是还没有实现我们的最终目的:实现自定义的表单验证
接下来我们创建一个正则验证器,新建文件 validate-register.ts :

import { ValidatorFn, AbstractControl } from '@angular/forms';

 export function validateRex(type: string, validateRex: RegExp): ValidatorFn {
 return (control: AbstractControl): {[key: string]: any} => {
  // 获取当前控件的内容
  const str = control.value;
  // 设置我们自定义的验证类型
  const res = {};
  res[type] = {str}
  // 如果验证通过则返回 null 否则返回一个对象(包含我们自定义的属性)
  return validateRex.test(str) ? null : res;
 }
 }

下面我们在代码中导入此函数:

import { validateRex } from './validate-register';

修改 validationMessage 属性为:

// 为每一项表单验证添加说明文字
 validationMessage = {
 'username': {
  'minlength': '用户名长度最少为3个字符',
  'maxlength': '用户名长度最多为10个字符',
  'required': '请填写用户名',
  'notdown': '用户名不能以下划线开头',
  'only': '用户名只能包含数字、字母、下划线'
 }
 };

修改 buildForm 方法:

// 通过 formBuilder构建表单
 this.registerForm = this.fb.group({
 /* 为 username 添加 5 项验证规则:
 * 1.必填, 2.最大长度为10, 3.最小长度为3, 4.不能以下划线开头, 5.只能包含数字、字母、下划线
 * 其中第一个空字符串参数为表单的默认值
 */
 'username': [ '', [
  Validators.required,
  Validators.maxLength(10),
  Validators.minLength(3),
  validateRex('notdown', /^(?!_)/),
  validateRex('only', /^[1-9a-zA-Z_]+$/)
 ]]
 });

OK ! 大功告成了,赶紧运行代码尝试一下吧,我们可以随时添加各种验证规则,只需要修改 validationMessage 属性和 buildForm 方法即可!

如果添加多个表单控件的话还需要修改 formErrors,例如添加 password 控件则修改 formErrors 为

formErrors = {
 username: '',
 password: ''
};

大家可自行尝试一下!

完整代码:

register.component.html 

<h3 class="text-center">注册</h3>

 <form [formGroup]="registerForm" >

 <div class="form-group">
  <label for="username">用户名:</label>

  <input formControlName="username"
  type="text" id="username" #username
  class="form-control" >
  <div *ngIf="formErrors.username" class="showerr alert alert-danger" >{{ formErrors.username }}</div>
 </div>

 </form>

register.component.css:

form {
 width: 90%;
 max-width: 45em;
 margin: auto;
 }

 .showerr {
 white-space: pre-wrap;
 }

register.component.ts:

import { Component, OnInit } from '@angular/core';
 import { FormBuilder, FormGroup, Validators } from '@angular/forms';
 import { validateRex } from './validate-register';

 @Component({
 selector: 'app-register',
 templateUrl: './register.component.html',
 styleUrls: ['./register.component.css']
 })
 export class RegisterComponent implements OnInit {

 // 定义表单
 registerForm: FormGroup;

 // 表单验证不通过时显示的错误消息
 formErrors = {
  username: ''
 };

 // 为每一项表单验证添加说明文字
 validationMessage = {
  'username': {
  'minlength': '用户名长度最少为3个字符',
  'maxlength': '用户名长度最多为10个字符',
  'required': '请填写用户名',
  'notdown': '用户名不能以下划线开头',
  'only': '用户名只能包含数字、字母、下划线'
  }
 };

 // 添加 fb 属性,用来创建表单
 constructor(private fb: FormBuilder) { }

 ngOnInit() {
  // 初始化时构建表单
  this.buildForm();
 }

 // 构建表单方法
 buildForm(): void {
  // 通过 formBuilder构建表单
  this.registerForm = this.fb.group({
  /* 为 username 添加3项验证规则:
  * 1.必填, 2.最大长度为10, 3.最小长度为3, 4.不能以下划线开头, 5.只能包含数字、字母、下划线
  * 其中第一个空字符串参数为表单的默认值
  */
  'username': [ '', [
   Validators.required,
   Validators.maxLength(10),
   Validators.minLength(3),
   validateRex('notdown', /^(?!_)/),
   validateRex('only', /^[1-9a-zA-Z_]+$/)
  ]]
  });

  // 每次表单数据发生变化的时候更新错误信息
  this.registerForm.valueChanges
  .subscribe(data => this.onValueChanged(data));

  // 初始化错误信息
  this.onValueChanged();
 }

 // 每次数据发生改变时触发此方法
 onValueChanged(data?: any) {
  // 如果表单不存在则返回
  if (!this.registerForm) return;
  // 获取当前的表单
  const form = this.registerForm;

  // 遍历错误消息对象
  for (const field in this.formErrors) {
  // 清空当前的错误消息
  this.formErrors[field] = '';
  // 获取当前表单的控件
  const control = form.get(field);

  // 当前表单存在此空间控件 && 此控件没有被修改 && 此控件验证不通过
  if (control && control.dirty && !control.valid) {
   // 获取验证不通过的控件名,为了获取更详细的不通过信息
   const messages = this.validationMessage[field];
   // 遍历当前控件的错误对象,获取到验证不通过的属性
   for (const key in control.errors) {
   // 把所有验证不通过项的说明文字拼接成错误消息
   this.formErrors[field] += messages[key] + '\n';
   }
  }
  }
 }

 }

validate-register.ts:

import { ValidatorFn, AbstractControl } from '@angular/forms';

 export function validateRex(type: string, validateRex: RegExp): ValidatorFn {
 return (control: AbstractControl): {[key: string]: any} => {
  // 获取当前控件的内容
  const str = control.value;
  // 设置我们自定义的严重类型
  const res = {};
  res[type] = {str}
  // 如果验证通过则返回 null 否则返回一个对象(包含我们自定义的属性)
  return validateRex.test(str) ? null : res;
 }
 }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
css配合jquery美化 select
Nov 29 Javascript
js面向对象之静态方法和静态属性实例分析
Jan 10 Javascript
javascript实现简单的二级联动
Mar 19 Javascript
javascript实现别踩白块儿小游戏程序
Nov 22 Javascript
微信小程序  modal详解及实例代码
Nov 09 Javascript
jQuery源码分析之init的详细介绍
Feb 13 Javascript
10个最优秀的Node.js MVC框架
Aug 24 Javascript
JS实现按钮添加背景音乐示例代码
Oct 17 Javascript
Node中使用ES6语法的基础教程
Jan 05 Javascript
vue-music 使用better-scroll遇到轮播图不能自动轮播问题
Dec 03 Javascript
js实现单元格拖拽效果
Feb 10 Javascript
Webpack5正式发布,有哪些新特性
Oct 12 Javascript
微信小程序 侧滑删除(左滑删除)
May 23 #Javascript
最常用的jQuery表单验证(简单)
May 23 #jQuery
jquery实现简单实用的轮播器
May 23 #jQuery
vue.js 左侧二级菜单显示与隐藏切换的实例代码
May 23 #Javascript
Bootstrap多级菜单的实现代码
May 23 #Javascript
微信小程序获取用户openId的实现方法
May 23 #Javascript
详解vuex 中的 state 在组件中如何监听
May 23 #Javascript
You might like
创建配置文件 用PHP写出自己的BLOG系统 2
2010/04/12 PHP
探讨:如何编写PHP扩展
2013/06/13 PHP
PHP中使用SimpleXML检查XML文件结构实例
2015/01/07 PHP
laravel5.6实现数值转换
2019/10/23 PHP
javaScript让文本框内的最后一个文字的后面获得焦点实现代码
2013/01/06 Javascript
JQuery获取各种宽度、高度(format函数)实例
2013/03/04 Javascript
jQuery获取CSS样式中的颜色值的问题,不同浏览器格式不同的解决办法
2013/05/13 Javascript
Flexigrid在IE下不显示数据的处理的解决方法
2013/10/24 Javascript
JS实现切换标签页效果实例代码
2013/11/01 Javascript
js实现回放拖拽轨迹从过程上进行分析
2014/06/26 Javascript
详解JavaScript的while循环的使用
2015/06/03 Javascript
Jquery Mobile 自定义按钮图标
2015/11/18 Javascript
BootStrap智能表单实战系列(十一)级联下拉的支持
2016/06/13 Javascript
node.js实现快速截图
2016/08/27 Javascript
Javascript农历与公历相互转换的简单实例
2016/10/09 Javascript
JS控制页面跳转时未请求要跳转的地址怎么回事
2016/10/14 Javascript
jQuery插件MovingBoxes实现左右滑动中间放大图片效果
2017/02/28 Javascript
nodejs使用http模块发送get与post请求的方法示例
2018/01/08 NodeJs
微信小程序实现点击导航标签滚动定位到对应位置
2020/11/19 Javascript
javascript实现移动端轮播图
2020/12/09 Javascript
Python入门_学会创建并调用函数的方法
2017/05/16 Python
pandas 实现字典转换成DataFrame的方法
2018/07/04 Python
详解Django中类视图使用装饰器的方式
2018/08/12 Python
Windows下Anaconda2安装NLTK教程
2018/09/19 Python
如何用css3实现switch组件开关的方法
2018/02/09 HTML / CSS
双立人加拿大官网:Zwilling加拿大
2020/08/10 全球购物
PHP数据运算类型都有哪些
2013/11/05 面试题
策划创业计划书
2014/02/06 职场文书
机关搬迁方案
2014/05/18 职场文书
班主任经验交流材料
2014/12/16 职场文书
员工辞退通知书
2015/04/17 职场文书
2015年度信用社工作总结
2015/05/04 职场文书
清明祭英烈活动总结
2015/05/11 职场文书
无房证明样本
2015/06/17 职场文书
毕业生求职自荐信(2016最新版)
2016/01/28 职场文书
深入理解Vue的数据响应式
2021/05/15 Vue.js