校验器逻辑定义:
import {FormControl, FormGroup, AbstractControl, ValidatorFn} from '@angular/forms';
export function usernameValidator(control: FormControl): any {
const usernameRegex = /^[a-zA-Z0-9_]{4,8}$/;
return usernameRegex.test(control.value) ? null : {username: true};
}
export function textValidator(control: FormControl): any { // 中英文 + 数字 + 全角标点
const textRegex = /^[\u4e00-\u9fa5\u3000-\u301e\ufe10-\ufe19\ufe30-\ufe44\ufe50-\ufe6b\uff01-\uffee_a-zA-Z0-9]+$/;
return textRegex.test(control.value) ? null : {text: true};
}
export function truenameValidator(control: FormControl): any {
const truenameRegex = /(^[\u4e00-\u9fa5]{1}[\u4e00-\u9fa5\.·。]{0,8}[\u4e00-\u9fa5]{1}$)|(^[a-zA-Z]{1}[a-zA-Z\s]{0,8}[a-zA-Z]{1}$)/;
return truenameRegex.test(control.value) ? null : {truename: true};
}
export function baseValidator(control: FormControl): any { // 中英文(不包括非法字符)
const _baseValidator = /(^[\u4e00-\u9fa5]{1}[\u4e00-\u9fa5\.·]{0,18}[\u4e00-\u9fa5]{1}$)|(^[a-zA-Z]{1}[a-zA-Z\s]{0,18}[a-zA-Z]{1}$)/;
const baseValid = _baseValidator.test(control.value);
return baseValid ? null : {truename: true};
}
export function mobileValidator(control: FormControl): any {
const mobileRegex = /^1[3|4|5|7|8][0-9]\d{8}$/;
return mobileRegex.test(control.value) ? null : {mobile: true};
}
export function numberValidator(control: FormControl): any {
const numberRegex = /^[0-9]*[0-9]*$/;
return numberRegex.test(control.value) ? null : {number: true};
}
export function idNumberValidator(control: FormControl): any {
const aCity = {
11: '北京', 12: '天津', 13: '河北', 14: '山西', 15: '内蒙古', 21: '辽宁', 22: '吉林', 23: '黑龙江',
31: '上海', 32: '江苏', 33: '浙江', 34: '安徽', 35: '福建', 36: '江西', 37: '山东', 41: '河南', 42: '湖北',
43: '湖南', 44: '广东', 45: '广西', 46: '海南', 50: '重庆', 51: '四川', 52: '贵州', 53: '云南', 54: '西藏',
61: '陕西', 62: '甘肃', 63: '青海', 64: '宁夏', 65: '新疆', 71: '台湾', 81: '香港', 82: '澳门', 91: '国外'
};
let iSum = 0, sId = control.value;
if (!/^\d{17}(\d|x)$/i.test(sId)) {
return {identify: true};
}
sId = sId.replace(/x$/i, 'a');
if (aCity[+sId.substr(0, 2)] === null) {
return {identify: true};
}
const sBirthday = sId.substr(6, 4) + '-' + +sId.substr(10, 2) + '-' + +sId.substr(12, 2);
const d = new Date(sBirthday.replace(/-/g, '/'));
if (sBirthday !== (d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + d.getDate())) {
return {identify: true};
}
for (let i = 17; i >= 0; i--) {
iSum += (Math.pow(2, i) % 11) * parseInt(sId.charAt(17 - i), 11);
}
if (iSum % 11 !== 1) {
return {identify: true};
}
return null;
}
export function emailValidator(control: FormControl): any {
const emailRegex = /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
return emailRegex.test(control.value) ? null : {email: true};
}
export function notEmptyValidator(control: FormControl): any {
return control.value !== '' ? null : {notEmpty: true};
}
export function dateValidator(control: FormControl): any {
// tslint:disable-next-line:max-line-length
const dateRegex = /^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$/;
return dateRegex.test(control.value) ? null : {date: true};
}
export function equalValidator(group: FormGroup): any {
return group.get('password').value === group.get('pconfirm').value ? null : {equal: true};
}
export function listValidator(_listValidator: Set<string>): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } => _listValidator.has(control.value) ? null : {list: true};
}
export function urlValidator(control: FormControl): any {
const _urlRegex = '^((https|http|ftp|rtsp|mms)?://)'
+ '?(([0-9a-z_!~*\'().&=+$%-]+: )?[0-9a-z_!~*\'().&=+$%-]+@)?' // ftp的user@
+ '(([0-9]{1,3}\.){3}[0-9]{1,3}' // IP形式的URL- 199.194.52.184
+ '|' // 允许IP和DOMAIN(域名)
+ '([0-9a-z_!~*\'()-]+\.)*' // 域名- www.
+ '([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\.' // 二级域名
+ '[a-z]{2,6})' // first level domain- .com or .museum
+ '(:[0-9]{1,4})?' // 端口- :80
+ '((/?)|' // a slash isn't required if there is no file name
+ '(/[0-9a-z_!~*\'().;?:@&=+$,%#-]+)+/?)$';
const urlRegex = new RegExp(_urlRegex);
return urlRegex.test(control.value) ? null : {date: true};
}
export function telValidator(control: FormControl): any {
const telRegex = /^(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}$/;
return telRegex.test(control.value) ? null : {mobile: true};
}
校验器的使用:
LIST 校验器:
const _listValidator = {
dept: listValidator(new Set(this.staffDeptList.map(ele => ele['deptName']))),
type: listValidator(new Set(this.staffTypeList.map(ele => ele['typeName']))),
title: listValidator(new Set(this.staffTitleList.map(ele => ele['typeName']))),
position: listValidator(new Set(this.staffPositionList.map(ele => ele['typeName']))),
grade: listValidator(new Set(this.staffGradeList.map(ele => ele['typeName'])))
};
this.formModelAdd.get('staffDept').setValidators(_listValidator.dept);
this.formModelAdd.get('staffType').setValidators(_listValidator.type);
this.formModelAdd.get('staffTitle').setValidators(_listValidator.title);
this.formModelAdd.get('staffPosition').setValidators(_listValidator.position);
this.formModelAdd.get('staffGrade').setValidators(_listValidator.grade);
其他校验器
this.formControlsConfig = {
staffId: ['', numberValidator],
userName: ['', truenameValidator],
phoneNum: ['', mobileValidator],
idNum: ['', idNumberValidator],
staffDept: ['', null],
staffType: ['', null],
staffTitle: ['', null],
staffPosition: ['', null],
staffGrade: ['', null],
staffAddress: ['', notEmptyValidator]
};
this.formModelAdd = fb.group(this.formControlsConfig);
HTML 中的使用
<div class="input-group mb-2">
<span class="input-group-text">身份证号</span>
<input type="text" class="form-control col-md-9" [placeholder]="ph.iid" required formControlName="idNum" [tooltip]="tooltips.aiid"/>
</div>
<div class="input-group mb-2">
<span class="input-group-text">人事科室</span>
<input list="adept" class="form-control col-md-9" [placeholder]="ph.dept" formControlName="staffDept" [tooltip]="tooltips.adept" required/>
<datalist id="adept">
<option class="form-control" *ngFor="let staffDept of staffDeptList" [value]="staffDept['deptName']">
{{staffDept['deptPyCode']}}
</option>
</datalist>
</div>
样式:
input.ng-pristine[required] {
border-left: 4px solid #39afea;
}
input.ng-invalid.ng-dirty:not(form) {
border-left: 4px solid #a94442;
/* red */
}
input.ng-valid.ng-dirty {
border-left: 4px solid #42A948;
/* green */
}
textarea.ng-pristine[required] {
border-left: 4px solid #39afea;
}
textarea.ng-invalid.ng-dirty:not(form) {
border-left: 4px solid #a94442;
/* red */
}
textarea.ng-valid.ng-dirty {
border-left: 4px solid #42A948;
/* green */
}
select.ng-pristine[required] {
border-left: 4px solid #39afea;
}
select.ng-invalid.ng-dirty:not(form) {
border-left: 4px solid #a94442;
/* red */
}
select.ng-valid.ng-dirty {
border-left: 4px solid #42A948;
/* green */
}
网友评论