表单校验
- 校验器
- 校验响应式表单
- 校验模板式表单
1、校验器格式
方法名(control:AbstractControl):{[key]:string:any}{
return null;
}
校验器的参数control必须是AbstractControl类型的,返回的是个对象{};对象的key必须是string类型的,值是any类型的;
默认的校验器是Validators用required,minlength,maxlength等
校验响应式表单 案例
新建组件
ng g component reactRegist
app下新建validator文件夹,新建validators.ts文件
代码如下:
import {FormControl, FormGroup} from "@angular/forms";
import 'rxjs/Rx';
import {Observable} from "rxjs/Observable";
//import 'rxjs/add/observable/of';
//自定义手机校验器
export function mobileValidator(control:FormControl):any{
//手机的正则表达式
var myreg = /^(((13[0-9]{1})|(15[0-9]{1})|(18[0-9]{1}))+\d{8})$/;
let valid = myreg.test(control.value);
console.log("mobile的校验结果是:"+valid);
return valid ? null:{mobile:true};
}
//异步校验器
export function mobileAsyncValidator(control:FormControl):any{
//手机的正则表达式
var myreg = /^(((13[0-9]{1})|(15[0-9]{1})|(18[0-9]{1}))+\d{8})$/;
let valid = myreg.test(control.value);
console.log("mobile的校验结果是:"+valid);
//返回数据流,delay模拟延迟5秒钟返回
return Observable.of(valid ? null:{mobile:true}).delay(5000) ;
}
//密码校验器
export function equalValidator(group:FormGroup):any{
//取得密码
let password:FormControl = group.get("password") as FormControl;
//取得重复密码
let pconfirm:FormControl = group.get("pconfirm") as FormControl;
//比较结果
let valid:boolean = (password.value === pconfirm.value);
console.log("密码校验结果:" +valid);
return valid ? null:{equal:{descxxx:'密码不一致'}};
}
react-regist.component.ts组件代码:
import { Component, OnInit } from '@angular/core';
import {FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms";
import {equalValidator, mobileAsyncValidator, mobileValidator} from "../valitator/validators";
@Component({
selector: 'app-react-regist',
templateUrl: './react-regist.component.html',
styleUrls: ['./react-regist.component.css']
})
export class ReactRegistComponent implements OnInit {
formModel:FormGroup;
constructor(fb:FormBuilder) {
this.formModel = fb.group({
username:['',[Validators.required,Validators.minLength(6)]],
mobile:['',mobileValidator,mobileAsyncValidator],
passwordsGroup:fb.group({
password:['',Validators.minLength(6)],
pconfirm:[''],
},{validator:equalValidator})
});
}
onSubmit(){
/*let isValid:boolean = this.formModel.get('username').valid;
console.log("username的校验结果:"+isValid);
let errors:any = this.formModel.get('username').errors;
//返回校验器的错误信息(含有key)
console.log("返回的错误信息是:"+JSON.stringify(errors));*/
if(this.formModel.valid){
console.log(this.formModel.value);
}
}
ngOnInit() {
}
}
react-regist.component模块中
<form [formGroup]="formModel" (submit)="onSubmit()">
<div>
用户名:<input type="text" formControlName="username">
</div>
<!--错误提示-->
<div [hidden]="!formModel.hasError('required','username')">
用户名是必填项
</div>
<div [hidden]="!formModel.hasError('minlength','username')">
用户名最小长度是6
</div>
<div>
手机号:<input type="text" formControlName="mobile">
</div>
<div [hidden]="!formModel.hasError('mobile','mobile')">
手机号不正确
</div>
<div formGroupName="passwordsGroup">
<div>
密码:<input type="password" formControlName="password">
</div>
<div>
重复密码:<input type="password" formControlName="pconfirm" >
</div>
<!--错误信息-->
<div [hidden]="!formModel.hasError('equal','passwordsGroup')">
{{formModel.getError('equal','passwordsGroup')?.descxxx}}
</div>
<div [hidden]="!formModel.hasError('minlength',['passwordsGroup','password'])">
密码最小长度6位
</div>
</div>
<button type="submit">提交</button>
</form>
<div>
{{formModel.status}}
</div>
状态字段
- touched 触摸 未触摸 untouched
关注的字段是有没有获得焦点
- pristine 值有没有变过 dirty 值有改变过
关注的是字段的值变化
- pending
当一个字段在异步校验的时候,这时pending的属性是true
通过状态来给字段添加自定义样式
react-regist.component.html重构代码如下:
<form [formGroup]="formModel" (submit)="onSubmit()">
<div>
用户名:<input [class.hasError]="formModel.get('username').invalid && formModel.get('username').touched" type="text" formControlName="username">
</div>
<!--用户名 错误提示-->
<div [hidden]="formModel.get('username').valid || formModel.get('username').untouched">
<div [hidden]="!formModel.hasError('required','username')">
用户名是必填项
</div>
<div [hidden]="!formModel.hasError('minlength','username')">
用户名最小长度是6
</div>
</div>
<!--用户名 错误提示-->
<div>
手机号:<input type="text" formControlName="mobile">
</div>
<!-- 手机号 校验提示 -->
<div [hidden]="formModel.get('mobile').valid || formModel.get('mobile').pristine">
<div [hidden]="!formModel.hasError('mobile','mobile')">
手机号不正确
</div>
</div>
<div [hidden]="!formModel.get('mobile').pending">
正在校验手机号合法性
</div>
<!-- 手机号 校验提示 -->
<div formGroupName="passwordsGroup">
<div>
密码:<input type="password" formControlName="password">
</div>
<div>
重复密码:<input type="password" formControlName="pconfirm" >
</div>
<!--错误信息-->
<div [hidden]="!formModel.hasError('equal','passwordsGroup')">
{{formModel.getError('equal','passwordsGroup')?.descxxx}}
</div>
<div [hidden]="!formModel.hasError('minlength',['passwordsGroup','password'])">
密码最小长度6位
</div>
</div>
<button type="submit">提交</button>
</form>
<div>
{{formModel.status}}
</div>
react-regist.component.css 代码:
.hasError{
border: 1px solid palevioletred;
}
校验模板式表单 案例
- 模板式表单通过自定义指令校验;
- 自定义指令可以理解为没有模板的组件,使用用@Directive装饰器
- 自定义指令在HTML中可以当做属性来用
新建组件
ng g component templateForm
ng g directive directives/mobileValidator
ng g directive directives/equalValidator
equal-validator.directive.ts代码:
import { Directive } from '@angular/core';
import {NG_VALIDATORS} from "@angular/forms";
import {equalValidator} from "../valitator/validators";
@Directive({
selector: '[equal]',
providers:[{provide:NG_VALIDATORS,useValue:equalValidator,multi:true}]
})
export class EqualValidatorDirective {
constructor() { }
}
mobile-validator.directive.ts代码:
import { Directive } from '@angular/core';
import {NG_VALIDATORS} from "@angular/forms";
import {mobileValidator} from "../valitator/validators";
@Directive({
selector: '[mobile]',
providers:[{provide:NG_VALIDATORS,useValue:mobileValidator,multi:true}]
})
export class MobileValidatorDirective {
constructor() { }
}
template-form.component.html代码
<form #myForm="ngForm" (ngSubmit)="onSubmit(myForm.value,myForm.valid)" novalidate>
<div>用户名:<input ngModel required minlength="6" name="username" type="text" (input)="onUserInput(myForm)" ></div>
<!-- 用户名校验 -->
<div [hidden]="userValid||userUntouched">
<div [hidden]="!myForm.form.hasError('required','username')">
用户名是必填项
</div>
<div [hidden]="!myForm.form.hasError('minlength','username')">
用户名最小长度是6
</div>
</div>
template-form.component.ts代码
import {Component, OnInit} from '@angular/core';
import {NgForm} from "@angular/forms";
@Component({
selector: 'app-template-form',
templateUrl: './template-form.component.html',
styleUrls: ['./template-form.component.css']
})
export class TemplateFormComponent implements OnInit {
constructor() {
}
ngOnInit() {
}
mobileValid: boolean = true;
mobileUntouched: boolean = true;
onMobileInput(form: NgForm) {
if (form) {
this.mobileValid = form.form.get('mobile').valid;
this.mobileUntouched = form.form.get('mobile').untouched;
}
}
userValid: boolean = true;
userUntouched: boolean = true;
onUserInput(form: NgForm) {
if (form) {
this.userValid = form.form.get('username').valid;
this.userUntouched = form.form.get('username').untouched;
}
}
onSubmit(value: any, valid: boolean) {
console.log(valid);
console.log(value);
}
}
源码 链接:http://pan.baidu.com/s/1cpWvW6 密码:zhog