强大的 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 相关文章推荐
效率高的Javscript字符串替换函数的benchmark
Aug 02 Javascript
js判断IE6/IE7/FF的代码[XMLHttpRequest]
Feb 16 Javascript
jquery实现可旋转可拖拽的文字效果代码
Jan 27 Javascript
JS中的作用域链
Mar 01 Javascript
vue.js动画中的js钩子函数的实现
Jul 06 Javascript
webpack之引入图片的实现及问题
Oct 08 Javascript
详解微信小程序之scroll-view的flex布局问题
Jan 16 Javascript
小程序getLocation需要在app.json中声明permission字段
Apr 04 Javascript
javascript实现的时间格式加8小时功能示例
Jun 13 Javascript
Nuxt使用Vuex的方法示例
Sep 06 Javascript
JS Ajax请求会话过期处理问题解决方法分析
Nov 16 Javascript
JavaScript如何判断input数据类型
Feb 06 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 将bmp图片转为jpg等其他任意格式的图片
2009/06/21 PHP
PHP对字符串的递增运算分析
2010/08/08 PHP
php微信开发自定义菜单
2016/08/27 PHP
php 时间time与日期date之间的使用详解及区别
2016/11/07 PHP
用PHP将Unicode 转化为UTF-8的实现方法(推荐)
2017/02/08 PHP
Ajax+Jpgraph实现的动态折线图功能示例
2019/02/11 PHP
php 中的信号处理操作实例详解
2020/03/04 PHP
Javascript 通过json自动生成Dom的代码
2010/04/01 Javascript
FusionCharts图表显示双Y轴双(多)曲线
2012/11/22 Javascript
JQuery入门——移除绑定事件unbind方法概述及应用
2013/02/05 Javascript
JS添加删除一组文本框并对输入信息加以验证判断其正确性
2013/04/11 Javascript
jquery获取当前点击对象的value方法
2014/02/28 Javascript
jquery实现效果比较好的table选中行颜色
2014/03/25 Javascript
jquery处理json数据实例分析
2014/06/03 Javascript
浅谈js中字符和数组一些基本算法题
2016/08/15 Javascript
jquery与js实现全选功能的区别
2017/06/11 jQuery
BootStrap Fileinput上传插件使用实例代码
2017/07/28 Javascript
jQuery轻量级表单模型验证插件
2018/10/15 jQuery
利用Electron简单撸一个Markdown编辑器的方法
2019/06/10 Javascript
vue的keep-alive用法技巧
2019/08/15 Javascript
详解Vue 换肤方案验证
2019/08/28 Javascript
JS 设计模式之:单例模式定义与实现方法浅析
2020/05/06 Javascript
ES11新增的这9个新特性,你都掌握了吗
2020/10/15 Javascript
python逐行读取文件内容的三种方法
2014/01/20 Python
Python实现的HTTP并发测试完整示例
2020/04/23 Python
Python学习之Django的管理界面代码示例
2018/02/10 Python
python logging重复记录日志问题的解决方法
2018/07/12 Python
python pandas消除空值和空格以及 Nan数据替换方法
2018/10/30 Python
python interpolate插值实例
2020/07/06 Python
公司道歉信范文
2014/01/09 职场文书
送餐员岗位职责范本
2014/02/21 职场文书
八项规定整改方案
2014/10/01 职场文书
离婚协议书范本
2015/01/26 职场文书
初中思想品德教学反思
2016/02/24 职场文书
致创业的您:这类人不适合餐饮创业
2019/08/19 职场文书
PYTHON InceptionV3模型的复现详解
2022/05/06 Python