Angular data13

表单校验

  • 校验器
  • 校验响应式表单
  • 校验模板式表单

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容

  • 史上最简单Angular2教程,大叔都学会了 作者:王芃 wpcfan@gmail.com 第一节:初识Angul...
    接灰的电子产品阅读 58,736评论 76 248
  • 本文将介绍如何动态创建表单组件,我们最终实现的效果如下: 在阅读本文之前,请确保你已经掌握 Angular 响应式...
    semlinker阅读 3,855评论 0 7
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,468评论 25 707
  • 火车悠悠地行驶着,窗外的景色不断在变化。 五年了,终于要来到他生活的城市,她魂牵梦绕的城市。都说是因为一个...
    两三点水阅读 789评论 5 2
  • 一直以来,我都在思所着同一个问题——究竟我能不能靠自己一个人好好的生活?我在怕什么?又在担忧什么?恐惧什么?我越来...
    雪铃航阅读 298评论 0 1