Angular5+ 自定义表单验证器
Angular5+ 自定义表单验证器
Custom Validators
标签(空格分隔): Angular
首先阐述一下遇到的问题:
- 怎样实现“再次输入密码”的验证(两个controller值相等)(equalTo)
- 怎样反向监听(先输入“再次输入密码”,后输入设置密码)
解决思路:
- 第一个问题,可以通过
[AbstractControl].root.get([targetName])来取得指定的controller,然后比较他们的值。 - 第二个,可以通过
[target].setErrors([errors])来实现。
- 这是一个我的自定义表单验证:
import {AbstractControl, FormGroup, ValidatorFn} from '@angular/forms';
import {G} from '../services/data-store.service';
export class MyValidators {
private static isEmptyInputValue(value) {
// we don't check for string here so it also works with arrays
return value == null || value.length === 0;
}
private static isEmptyObject(obj) {
if (typeof obj === 'object' && typeof obj.length !== 'number') {
return Object.keys(obj).length === 0;
}
return null;
}
/**
* 等于指定controller的值
* @param targetName 目标的formControlName
* @returns {(ctrl: FormControl) => {equalTo: {valid: boolean}}}
*/
static equalTo(targetName: string): ValidatorFn {
return (control: AbstractControl): {[key: string]: any} | null => {
const target = control.root.get(targetName);
if (target === null) {
return null;
}
if (this.isEmptyInputValue(control.value)) {
return null;
}
return target.value === control.value ? null : {'equalto': { valid: false }};
};
}
/**
* 反向输入监听指定controller是否与当前值相等
* @param targetName
*/
static equalFor(targetName: string): ValidatorFn {
return (control: AbstractControl): {[key: string]: any} | null => {
const target = control.root.get(targetName);
if (target === null) {
return null;
}
if (this.isEmptyInputValue(control.value)) {
return null;
}
if (target.value === control.value) {
const errors = target.errors;
delete errors['equalto'];
if (this.isEmptyObject(errors)) {
target.setErrors(null);
} else {
target.setErrors(errors);
}
return null;
}
target.setErrors({ 'equalto': { valid: false } });
};
}
...
}
(注:)其中G.REGEX等的是全局变量。
- 然后
FormBuilder来实现:
import { Component, OnInit } from '@angular/core';
import {EventsService} from '../../../services/events.service';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {G} from '../../../services/data-store.service';
import {fade} from '../../../animations/fade.animation';
import {MyValidators} from '../../../directives/my-validators.directive';
@Component({
selector: 'app-sign-up',
templateUrl: './sign-up.component.html',
styleUrls: ['./sign-up.component.scss'],
animations: [fade]
})
export class SignUpComponent implements OnInit {
signForm: FormGroup; // 表单组FormGroup
submitting: boolean; // 是否可以提交
validations = G.VALIDATIONS;
constructor(private eventsService: EventsService, private formBuilder: FormBuilder) {
this.submitting = false;
//
this.init();
}
ngOnInit() {
// 设置父组件标题
this.eventsService.publish('setSign', { title: '注册', subTitle: { name: '立即登录', uri: '/account/sign-in' } });
}
// 立即注册
onSubmit() {
console.log(this.signForm.getRawValue());
}
// 表单初始化
private init() {
this.signForm = this.formBuilder.group({
username: ['', Validators.compose([Validators.required, Validators.maxLength(this.validations.USR_MAX)])],
password: ['', Validators.compose([
Validators.required,
Validators.minLength(this.validations.PASS_MIN),
Validators.maxLength(this.validations.PASS_MAX),
MyValidators.equalFor('passwordConfirm')
])],
passwordConfirm: ['', Validators.compose([
Validators.required,
Validators.minLength(this.validations.PASS_MIN),
Validators.maxLength(this.validations.PASS_MAX),
MyValidators.equalTo('password')
])]
});
}
}
(注:)其中fade动画效果。
- 然后在html模板中,显示表单验证提示信息:
<form [formGroup]="signForm" (ngSubmit)="onSubmit()" class="sign-form" @fade>
<!-- 账号 -->
<div class="input-group username">
<span class="addon prev"><i class="civ civ-i-usr"></i></span>
<input type="text"
name="username"
class="form-control form-control-left default"
placeholder="请输入账号"
formControlName="username"
autocomplete="off">
<ul class="errors" *ngIf="signForm.get('username').invalid && (signForm.get('username').dirty || signForm.get('username').touched)">
<li *ngIf="signForm.get('username').hasError('required')" class="error">
请输入您的账号!
</li>
<li *ngIf="signForm.get('username').hasError('maxlength')" class="error">
账号不超过{{ validations.USR_MAX }}位!
</li>
</ul>
</div> <!-- /.账号 -->
<!-- 密码 -->
<div class="input-group password">
<span class="addon prev"><i class="civ civ-i-lock"></i></span>
<input type="password"
name="password"
class="form-control form-control-left default"
placeholder="请输入密码"
formControlName="password">
<ul class="errors" *ngIf="signForm.get('password').invalid && (signForm.get('password').dirty || signForm.get('password').touched)">
<li *ngIf="signForm.get('password').hasError('required')" class="error">
请输入您的密码!
</li>
<li *ngIf="signForm.get('password').hasError('minlength')" class="error">
请输入至少{{ validations.PASS_MIN }}位数的密码!
</li>
<li *ngIf="signForm.get('password').hasError('maxlength')" class="error">
密码不超过{{ validations.PASS_MAX }}位!
</li>
</ul>
</div> <!-- /.密码 -->
<!-- 重复密码 -->
<div class="input-group password-confirm">
<span class="addon prev"><i class="civ civ-i-lock"></i></span>
<input type="password"
name="passwordConfirm"
class="form-control form-control-left default"
placeholder="请再次输入密码"
formControlName="passwordConfirm">
<ul class="errors" *ngIf="signForm.get('passwordConfirm').invalid && (signForm.get('passwordConfirm').dirty || signForm.get('passwordConfirm').touched)">
<li *ngIf="signForm.get('passwordConfirm').hasError('required')" class="error">
请再次输入密码!
</li>
<li *ngIf="signForm.get('passwordConfirm').hasError('minlength')" class="error">
请输入至少{{ validations.PASS_MIN }}位数的密码!
</li>
<li *ngIf="signForm.get('passwordConfirm').hasError('maxlength')" class="error">
密码不超过{{ validations.PASS_MAX }}位!
</li>
<li *ngIf="!signForm.get('passwordConfirm').hasError('maxlength') && !signForm.get('passwordConfirm').hasError('minlength') && signForm.get('passwordConfirm').hasError('equalto')" class="error">
两次密码输入不一致!
</li>
</ul>
</div> <!-- /.重复密码 -->
<!-- 提交按钮 -->
<button type="submit"
class="btn btn-primary btn-block submit"
[disabled]="submitting || signForm.invalid">立即注册</button>
<!-- /.提交按钮 -->
</form>
最后,我们可以看到,实现了想要的效果:

(附:)完整的自定义表单验证器:
import {AbstractControl, FormGroup, ValidatorFn} from '@angular/forms';
import {G} from '../services/data-store.service';
export class MyValidators {
private static isEmptyInputValue(value) {
// we don't check for string here so it also works with arrays
return value == null || value.length === 0;
}
private static isEmptyObject(obj) {
if (typeof obj === 'object' && typeof obj.length !== 'number') {
return Object.keys(obj).length === 0;
}
return null;
}
/**
* 等于指定controller的值
* @param targetName 目标的formControlName
* @returns {(ctrl: FormControl) => {equalTo: {valid: boolean}}}
*/
static equalTo(targetName: string): ValidatorFn {
return (control: AbstractControl): {[key: string]: any} | null => {
const target = control.root.get(targetName);
if (target === null) {
return null;
}
if (this.isEmptyInputValue(control.value)) {
return null;
}
return target.value === control.value ? null : {'equalto': { valid: false }};
};
}
/**
* 反向输入监听指定controller是否与当前值相等
* @param targetName
*/
static equalFor(targetName: string): ValidatorFn {
return (control: AbstractControl): {[key: string]: any} | null => {
const target = control.root.get(targetName);
if (target === null) {
return null;
}
if (this.isEmptyInputValue(control.value)) {
return null;
}
if (target.value === control.value) {
const errors = target.errors;
delete errors['equalto'];
if (this.isEmptyObject(errors)) {
target.setErrors(null);
} else {
target.setErrors(errors);
}
return null;
}
target.setErrors({ 'equalto': { valid: false } });
};
}
/**
* 验证手机号
* @returns {(ctrl: FormControl) => {mobile: {valid: boolean}}}
*/
static get mobile() {
return (control: AbstractControl) => {
if (this.isEmptyInputValue(control.value)) {
return null;
}
const valid = G.REGEX.MOBILE.test(control.value);
return valid ? null : {
'mobile': {
valid: false
}
};
};
}
/**
* 验证身份证
* @returns {(ctrl: FormControl) => {idCard: {valid: boolean}}}
*/
static get idCard() {
return (control: AbstractControl) => {
if (this.isEmptyInputValue(control.value)) {
return null;
}
const valid = G.REGEX.ID_CARD.test(control.value);
return valid ? null : {
'idcard': {
valid: false
}
};
};
}
/**
* 验证汉字
* @returns {(ctrl: FormControl) => {cn: {valid: boolean}}}
*/
static get cn() {
return (control: AbstractControl) => {
if (this.isEmptyInputValue(control.value)) {
return null;
}
const valid = G.REGEX.CN.test(control.value);
return valid ? null : {
'cn': {
valid: false
}
};
};
}
/**
* 指定个数数字
* @param {number} length
* @returns {(ctrl: FormControl) => (null | {number: {valid: boolean}})}
*/
static number(length: number = 6) {
return (control: AbstractControl) => {
if (this.isEmptyInputValue(control.value)) {
return null;
}
const valid = new RegExp(`^\\d{${length}}$`).test(control.value);
return valid ? null : {
'number': {
valid: false
}
};
};
}
/**
* 强密码(必须包含数字字母)
* @returns {(ctrl: FormControl) => (null | {number: {valid: boolean}})}
*/
static get strictPass() {
return (control: AbstractControl) => {
if (this.isEmptyInputValue(control.value)) {
return null;
}
const valid = G.REGEX.STRICT_PASS.test(control.value);
return valid ? null : {
'strictpass': {
valid: false
}
};
};
}
}
Angular5+ 自定义表单验证器的更多相关文章
- 五十四:WTForms表单验证之自定义表单验证器
如果想要对表单中的某个字段进行自定义验证,则需要对这个字段进行单独的验证1.定义一个方法,命名规则为:validate_字段名(self, filed)2.在方法中,使用filed.data获取字段的 ...
- AngularJS自定义表单验证器
<!doctype html> <html ng-app="myApp"> <head> <script src="G:\\So ...
- layui 自定义表单验证的几个实例
*注:使用本方法请先引入layui依赖的layu.js和layui.css 1.html <input type="text" name="costbudget&q ...
- Angular自定义表单验证
前端表单验证 为年龄输入框添加了两个验证,并分情况填写了提示语 <form nz-form [formGroup]="validateForm"> <nz-for ...
- jquery.validate.js使用之自定义表单验证规则
jquery.validate.js使用之自定义表单验证规则,下面列出了一些常用的验证法规则 jquery.validate.js演示查看 jquery validate强大的jquery表单验证插件 ...
- angular4 自定义表单验证Validator
表单的验证条件有时候满足不了需求就可以自定义验证 唯一要求返回是ValidatorFn export interface ValidatorFn{ (c:AbstractControl):Valida ...
- element自定义表单验证
element-ui框架下修改密码弹窗进行表单验证. 除了基础校验,密码不为空,长度不小于6字符,需求中还需校验密码由数字和字母组合. 处理代码如下: <el-dialog :visible.s ...
- ElementUI使用问题记录:设置路由+iconfont图标+自定义表单验证
一.关于导航怎么设置路由 1.在el-menu这个标签的属性中添加 router ,官方文档的解释是:启用vue-router 这种模式 2.在el-menu-item标签中的index属性直接书写路 ...
- 自定义表单验证--jquery validator addMethod的使用
原文地址:jquery validator addMethod 方法的使用作者:蜡笔小玄 jQuery.validate是一款非常不错的表单验证工具,简单易上手,而且能达到很好的体验效果,虽然说在项目 ...
随机推荐
- 2018南京icpc现场赛心得
第一次参加icpc的比赛,也是第一块奖牌,虽然只是铜,但其实打的已经很好了,稍微差一点就可以摸银了. 之前参加省赛,成为那次比赛我校唯一一个没拿奖的队伍,其实还是一直都有一些心结的,而这段时间和新的队 ...
- win10 sshsecureshellclient删除profile保存的信息
C:\Users\joe\AppData\Roaming\SSH
- Python+Selenium之通过batch跑脚本
例如在执行路径C:\Portal_Scripts\Scripts下的脚本CreateIndicativeBOP.py,可以在notepad里面编写如下: @echo off cd C:\Portal ...
- shell 操作符详解
= 赋值操作符,可以用于算术和字符串赋值 + 加法计算 - 减法运算 * 乘法运算 / 除法运算 ** 幂运算 % 模运算 取他除后的剩余数 因此这个十分好求公约数 += &qu ...
- QT跟VC++结合来进行插件的验证机制
由于最近公司要开发一个以C++插件机制为主的,主要有一个问题就是C++的二进制兼容性的问题.一旦类使用虚函数,只要随便改动下增删查改下头文件的虚函数,就会导致程序在跑的时候进行乱跳,因为这个时候exe ...
- (转)Linux下通过rsync与inotify(异步文件系统事件监控机制)实现文件实时同步
Linux下通过rsync与inotify(异步文件系统事件监控机制)实现文件实时同步原文:http://www.summerspacestation.com/linux%E4%B8%8B%E9%80 ...
- TOJ 1721 Partial Sums
Description Given a series of n numbers a1, a2, ..., an, the partial sum of the numbers is defined a ...
- 中文输入法无法在 QtCreator(Linux) 中输入汉字
中文输入法无法在 QtCreator(Linux) 中输入汉字 环境 system: Deepin 15.7 Qt Creator 4.7.0 (GCC 5.3.1) 解决方法 下载 fcitx-qt ...
- lxml库介绍及实例
XPath常用规则 表达式 描述 nodename 选取此节点的所有子节点 / 从当前节点选取直接子节点 // 从当前节点选取子孙节点 . 选取当前节点 .. 选取当前节点的父节点 @ 选取属性 h ...
- jstl标注标签库
1. 常用标签 引入标签库: <%@ taglib prefix=”c” uri=”” %> 1. C 标签 (1)<c:out value=”” default=” ...