美文网首页我爱编程
angular4 (5)表单处理

angular4 (5)表单处理

作者: mumumuu | 来源:发表于2018-06-19 16:52 被阅读0次

    <1>angular表单API

    40.png
    不同点 41.png

    注意
    要使用angular表单,要在app.module.ts中引入相应的模块
    模版式表单:FormsModule
    响应式表单:ReactiveFormsModule

    42.png

    <2>模版式表单

    使用模版式表单时,只能使用指令来定义数据模型。

    (1)NgForm

    用来代表整个表单,在angular项目中,它会自动添加到每个form标签上。
    示例:
    1.新建一个组件

    ng g component templateForm
    

    2.修改template-form.component.html

    <form action="/action" method="POST">
      <p>用户名:<input type="text"></p>
      <p>手机号:<input type="text"></p>
      <p>密码:<input type="password"></p>
      <p>确认密码:<input type="password"></p>
      <button type="submit">提交</button>
    </form>
    

    3.修改app.component.html

    <app-template-form></app-template-form>
    

    4.修改app.module.ts

    import { BrowserModule } from '@angular/platform-browser';
    import { AppComponent } from './app.component';
    import { TemplateFormComponent } from './template-form/template-form.component';
    import { NgModule } from '@angular/core';
    
    // 引入
    import { FormsModule } from '@angular/forms';
    
    @NgModule({
      declarations: [
        AppComponent,
        TemplateFormComponent
      ],
      imports: [
        BrowserModule,
        // 添加
        FormsModule
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
    
    

    5.界面

    43.png

    在非angular接管的表单中,点击提交,url会变成:localhost:4200/action,
    而angular接管的表单中,点击提交url不会有变化。
    若想要指定form不被angular接管,可以定义:

    <!-- 添加ngNoForm表示此表达不让angular接管 -->
    <form action="/action" method="POST" ngNoForm>
      <p>用户名:<input type="text"></p>
      <p>手机号:<input type="text"></p>
      <p>密码:<input type="password"></p>
      <p>确认密码:<input type="password"></p>
      <button type="submit">提交</button>
    </form>
    

    特性:ngForm指令可以被一个模版本地变量引用,以便在模版中访问ngForm对象的实例。
    例子:
    1.修改template-form.component.html

    <!-- 声明一个模板变量#myForm -->
    <form #myForm=ngForm action="/action" method="POST">
      <p>用户名:<input type="text"></p>
      <p>手机号:<input type="text"></p>
      <p>密码:<input type="password"></p>
      <p>确认密码:<input type="password"></p>
      <button type="submit">提交</button>
    </form>
    <!-- 下面通过这个模板变量来访问ngForm对象的属性 -->
    <!-- value是一个js对象,它保存了当前表单里面的值 -->
    {{myForm.value | json}}
    

    2.结果

    44.png

    (2)NgModel

    ngModel指令代表表单中的一个字段,这个指令会隐式的创建一个FormControl的实例,来代表字段的数据模型,并用这个FormControl类型的对象来存储字段的值。
    在上面例子的json中,当在表单中输入值时没有加到json中显示的原因是,那些input标签并未绑定ngModel指令。
    注意
    在ngForm中使用ngModel不需要像普通的数据双向绑定那样用[(ngModel)]的方式,直接写ngModel即可
    ngModel也可以使用模版变量来获取它的值
    示例
    1.

    <!-- 声明一个模板变量#myForm -->
    <form #myForm="ngForm" action="/action" method="POST">
      <!-- 给用户名绑定ngModel,并且声明一个模板变量#user -->
      <!-- 注意,一定要给标签声明一个name属性 -->
      <p>用户名:<input #user="ngModel" ngModel name="username" type="text"></p>
      <p>手机号:<input type="text"></p>
      <p>密码:<input type="password"></p>
      <p>确认密码:<input type="password"></p>
      <button type="submit">提交</button>
    </form>
    <!-- 下面通过这个模板变量来访问ngForm对象的属性 -->
    <!-- value是一个js对象,它保存了当前表单里面的值 -->
    {{myForm.value | json}}
    
    <!-- 用#user模板变量来获取用户名的值 -->
    {{username.value}}
    

    2.结果
    此时再次输入用户名时就会实时反映到下面的json中

    45.png

    当应用为单页应用并不需要跳转网页时,往往用ngSubmit来替代form标签的提交作用
    示例
    1.修改template-form.component.html

    <!-- 绑定ngSubmit,并定义一个方法fun,传入myForm的值到后台 -->
    <form #myForm="ngForm" (ngSubmit)="fun(myForm.value)" action="/action" method="POST">
      <p>用户名:<input #user="ngModel" ngModel name="username" type="text"></p>
      <p>手机号:<input type="text"></p>
      <p>密码:<input type="password"></p>
      <p>确认密码:<input type="password"></p>
      <button type="submit">提交</button>
    </form>
    {{myForm.value | json}}
    {{username.value}}
    

    2.修改template-form.component.spec.ts

    import { Component, OnInit } from '@angular/core';
    
    @Component({
      selector: 'app-template-form',
      templateUrl: './template-form.component.html',
      styleUrls: ['./template-form.component.css']
    })
    export class TemplateFormComponent implements OnInit {
    
      constructor() { }
    
      ngOnInit() {
      }
      onSubmit(value:any) {
        console.log(value);
      }
    }
    
    

    (3)NgModelGroup

    代表的是表单的一部分,它允许你将一些表单字段组织在一起,形成一个更清晰的层次关系,与ngForm指令类似,ngModelGroup指令也会创建一个FormGroup类的一个实例,这个实例会在ngForm对象的value属性中表现为一个嵌套的对象,所以说ngModelGroup的子属性都会变为这个嵌套对象的子属性
    示例
    1.修改template-form.component.html

    <form #myForm="ngForm" (ngSubmit)="onSubmit(myForm.value)">
      <!-- 嵌套一个ngModelGroup -->
      <div ngModelGroup="userInfo">
        <p>用户名:<input #user="ngModel" ngModel name="username" type="text"></p>
        <p>手机号:<input type="text"></p>
      </div>
      <p>密码:<input type="password"></p>
      <p>确认密码:<input type="password"></p>
      <button type="submit">提交</button>
    </form>
    <!-- 下面通过这个模板变量来访问ngForm对象的属性 -->
    <!-- value是一个js对象,它保存了当前表单里面的值 -->
    {{myForm.value | json}}
    
    <!-- 用#user模板变量来获取用户名的值 -->
    {{username.value}}
    

    2.结果
    username就被嵌套在userInfo中成为了userInfo的一个属性。

    46.png

    (4)重构用户注册表单的案例

    1.修改template-form.component.html

    <form #myForm="ngForm" (ngSubmit)="onSubmit(myForm.value)">
      <div ngModelGroup="userInfo">
        <p>用户名:<input #user="ngModel" ngModel name="username" type="text"></p>
        <p>手机号:<input ngModel name="phone" type="text"></p>
      </div>
      <!-- 嵌套一个ngModelGroup -->
      <div ngModelGroup="passwordsGroup">
        <p>密码:<input ngModel name="password" type="password"></p>
        <p>确认密码:<input ngModel name="pconfirm" type="password"></p>
      </div>
      <button type="submit">提交</button>
    </form>
    

    2.结果
    当输入结束,点击提交时

    47.png

    <3>响应式表单

    与模版式表单不同,创建一个响应式表单需要两步,首先需要编码来创建一个数据模型,然后需要使用些指令将模版中的html元素连接到这个数据模型上。

    1、数据模型

    是指用来保存表单数据的数据结构,简称模型。它由定义在angular的forms模块中的三个类组成。分别是:FormCotrol,FormGroup,FormArray

    (1)FormCotrol:是构成表单的基本单位,通常情况下它用来代表一个input元素,它也可以用来代表一个更复杂的UI组件,比如说日历、下拉选择块等。FormCotrol保存着与其关联的html元素当前的值以及元素的校验状态,还有元素是否被修改过等信息。

    如何创建一个FormCotrol,示例:

    //其中FormCotrol接收的参数aaa是username的初始值
    username:FormCotrol = new FormCotrol("aaa");
    

    (2)FormGroup:FormGroup既可以代表表单的一部分也可以用于代表整个表单,它是多个FormCotrol的集合,FormGroup将多个FormCotrol的值和状态聚合在一起。如果一个FormCotrol是无效的,那么整个FormGroup都是无效的。
    优点:在管理表单中多个相关联的字段时,使用FormGroup是很方便的,比如一个日期范围,有起始和终止日期两个input,这两个input可以放到一个FormGroup中,当其中一个任何一个字段的值无效时都会显示一个错误信息。

    如何创建一个FormGroup,示例:

    //FormGroup的构造函数需要一个对象
    formModel:FormGroup = new FormGroup({
        fromDate: new FormCotrol(),
        toDate: new FormCotrol()
    });
    

    (3)FormArray:FormArray和FormGroup是类似的,但是它有一个额外的长度属性,一般来说FormGroup用来代表整个表单或者表单字段的一个固定的子集。而FormArray通常用来代表一个可以增长的字段集合。

    如何创建一个FormArray,示例:

    //FormArray的构造函数是一个数组
    emails:FormArray = new FormArray([
        new FormCotrol("a@qq.com"),
        new FormCotrol("b@qq.com")
    ]);
    

    2、响应式表单指令

    48.png

    使用时,上图第二列要用属性绑定语法,即[formGroup]的形式,而第三列不需要用属性绑定语法。

    示例
    1.修改app.module.ts

    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    
    
    import { AppComponent } from './app.component';
    import { ReactiveFormComponent } from './reactive-form/reactive-form.component';
    
    // 引入响应式表单
    import { ReactiveFormsModule } from '@angular/forms';
    
    @NgModule({
      declarations: [
        AppComponent,
        ReactiveFormComponent
      ],
      imports: [
        BrowserModule,
        //引入
        ReactiveFormsModule
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
    
    

    2.修改reactive-form.component.ts

    import { Component, OnInit } from '@angular/core';
    
    //引入文件
    import { FormGroup,FormControl,FormArray } from '@angular/forms';
    @Component({
      selector: 'app-reactive-form',
      templateUrl: './reactive-form.component.html',
      styleUrls: ['./reactive-form.component.css']
    })
    export class ReactiveFormComponent implements OnInit {
    
      // 1.定义一个名为"myFormModel"的formGroup,用它来表示整个表单
      myFormModel:FormGroup = new FormGroup({
        // 3.声明一个formGroup,里面包含两个FormControl
        dateRange: new FormGroup({
          formDate:new FormControl(),
          toDate:new FormControl()
        }),
        emails:new FormArray([
          new FormControl("a@qq.com"),
          new FormControl("b@qq.com"),
          new FormControl("c@qq.com")
        ]),
        username2:new FormControl("name2")
    
      });
    
        // 5.定义一个名为username的FormControl
        username:FormControl = new FormControl("namenamename");
    
      constructor() { }
    
      ngOnInit() {
      }
      // 2.处理保存方法,打印myFormModel的值
      mySubmit(){
        console.log(this.myFormModel.value);
      }
    
      // 4.增加邮箱方法
      addEmail(){
        let emails = this.myFormModel.get("emails") as FormArray;
        emails.push(new FormControl());
      }
    }
    
    

    3.修改reactive-form.component.html

    <!-- 
      1.通常情况下,会用一个绑定到form标签的formGroup对象来代表整个表单
      用formGroup属性绑定到后台定义的myFormModel
      这样就把整个表单的处理方式变成了响应式表单的处理方式
     -->
     <!-- 2.提交方法 -->
    <form [formGroup] = "myFormModel" (submit)="mySubmit()">
      <!-- 3.用formGroupName来连接一个formGroup -->
      <div formGroupName="dateRange">
        <!-- 
          4.formControlName必须声明在formGroup内,来连接formGroup中的formControl和页面上的dom元素
         -->
        起始日期:<input type="date" formControlName="formDate"><br><br>
        截至日期:<input type="date"  formControlName="toDate">
      </div>
      <!-- 5.formArrayName也必须放在formGroup范围内 -->
      <div>
        <ul formArrayName="emails">
          <!-- 6.因为FormArray是用下标来显示每条数据的,所以一般配合ngFor来一起使用 -->
          <li *ngFor="let e of this.myFormModel.get('emails').controls;let i = index;" style="list-style: none">
            <!-- 这里要用属性绑定[formControlName] -->
            邮箱:<input type="text" [formControlName] = "i"><br>
          </li>
        </ul>
        <!-- 7.绑定click事件 -->
        <button type="button" (click)="addEmail()">增加email</button>
      </div>
      <div>
        <br>
        <button type="submit">保存</button>
      </div>
      <!-- 9.这种方式才会在formGroup的数据模型里 -->
      <input type="text" formControlName = "username2">
    </form>
    <br>
    <!-- 
      8.formControl指令不能放在formGroup的内部
        这个username不在formGroup里,所以点击保存不会打印出来
     -->
    <input type="text" [formControl] = "username">
    

    4.结果

    49.png

    3、响应式表单重构用户注册表

    1.修改app.module.ts

    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    
    
    import { AppComponent } from './app.component';
    import { ReactiveRigistComponent } from './reactive-rigist/reactive-rigist.component';
    
    //引入响应式表单
    import { ReactiveFormsModule } from '@angular/forms';
    
    @NgModule({
      declarations: [
        AppComponent,
        ReactiveRigistComponent
      ],
      imports: [
        BrowserModule,
        //引入响应式表单
        ReactiveFormsModule
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
    
    

    2.修改reactive-rigist.component.html

    <form [formGroup] = "myFormGroup">
      <p>用户名:<input type="text" formControlName = "username"></p>
      <p>手机号:<input type="text" formControlName = "mobile"></p>
      <div formGroupName = "passwordGroup">
        <p>密码:<input type="password" formControlName = "pwd"></p>
        <p>确认密码:<input type="password" formControlName = "pconfirm"></p>
      </div>
      <button type="submit" (click) = "mySubmit()">提交</button>
    </form>
    

    3.修改reactive-rigist.component.ts

    import { Component, OnInit } from '@angular/core';
    
    //引入
    import { FormGroup,FormControl } from '@angular/forms';
    
    @Component({
      selector: 'app-reactive-rigist',
      templateUrl: './reactive-rigist.component.html',
      styleUrls: ['./reactive-rigist.component.css']
    })
    export class ReactiveRigistComponent implements OnInit {
    
      myFormGroup:FormGroup;
      constructor() { 
        this.myFormGroup = new FormGroup({
          username:new FormControl(),
          mobile:new FormControl(),
          passwordGroup:new FormGroup({
            pwd:new FormControl(),
            pconfirm:new FormControl()
          })
        })
       }
      mySubmit(){
        console.log(this.myFormGroup.value);
      }
      ngOnInit() {
      }
    
    }
    

    4.结果

    50.png

    formBuilder

    将上个例子中的

    constructor() { 
        this.myFormGroup = new FormGroup({
          username:new FormControl(),
          mobile:new FormControl(),
          passwordGroup:new FormGroup({
            pwd:new FormControl(),
            pconfirm:new FormControl()
          })
        })
     }
    

    用 formBuilder 替换后

    constructor(fb:FormBuilder) { 
        this.myFormGroup = fb.group({
          username:[''],
          mobile:[''],
          passwordGroup:fb.group({
            pwd:[''],
            pconfirm:['']
          })
        })
       }
    

    最终的效果是一样的。

    <4>表单校验

    1、angular的校验器

    校验器就是一个普通的方法,该方法接收一个参数,参数类型必须为AbstractControl,必须要有一个返回值,返回值可以是任意结构的一个对象,这个对象的key必须是string类型的。
    例如:

    xxxx(control:AbstractControl):{[key:string]:any} {
       return null;
    }
    

    angular自带校验器例子:

    import { Component, OnInit} from '@angular/core';
    
    //引入
    import { FormGroup,FormControl,FormBuilder,Validators } from '@angular/forms';
    
    @Component({
      selector: 'app-reactive-rigist',
      templateUrl: './reactive-rigist.component.html',
      styleUrls: ['./reactive-rigist.component.css']
    })
    export class ReactiveRigistComponent implements OnInit {
      myFormGroup:FormGroup;
    
      constructor(fb:FormBuilder) { 
        this.myFormGroup = fb.group({
          // 第一个是默认值,第二个是校验器
          // 单个校验器的写法
          // username:['',[Validators.required,Validators.minLength(6)]],
          // 多个校验器的写法
          username:['',[Validators.required,Validators.minLength(6)]],
          mobile:[''],
          passwordGroup:fb.group({
            pwd:[''],
            pconfirm:['']
          })
        })
       }
      mySubmit(){
        let isValid:boolean = this.myFormGroup.get("username").valid;
    
        console.log("username的校验结果"+isValid);
        let errors:any = this.myFormGroup.get("username").errors;
    
        console.log("username的错误信息是"+JSON.stringify(errors));
        console.log(this.myFormGroup.value);
      }
      ngOnInit() {
      }
    
    }
    
    

    结果

    51.png

    2、自定义校验器

    1.

    import { Component, OnInit} from '@angular/core';
    
    //引入
    import { FormGroup,FormControl,FormBuilder,Validators } from '@angular/forms';
    
    @Component({
      selector: 'app-reactive-rigist',
      templateUrl: './reactive-rigist.component.html',
      styleUrls: ['./reactive-rigist.component.css']
    })
    export class ReactiveRigistComponent implements OnInit {
    
    //自定义手机号校验器
      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};
      }
      myFormGroup:FormGroup;
    
      constructor(fb:FormBuilder) { 
        this.myFormGroup = fb.group({
          username:['',[Validators.required,Validators.minLength(6)]],
          //添加自定义的校验器
          mobile:['',this.mobileValidator],
          passwordGroup:fb.group({
            pwd:[''],
            pconfirm:['']
          })
        })
       }
      mySubmit(){
        let isValid:boolean = this.myFormGroup.get("username").valid;
    
        console.log("username的校验结果"+isValid);
        let errors:any = this.myFormGroup.get("username").errors;
    
        console.log("username的错误信息是"+JSON.stringify(errors));
        console.log(this.myFormGroup.value);
      }
      ngOnInit() {
      }
    
    }
    
    

    2、结果

    52.png

    3、为FormGroup自定义校验器

    1、

    import { Component, OnInit} from '@angular/core';
    
    //引入
    import { FormGroup,FormControl,FormBuilder,Validators } from '@angular/forms';
    
    @Component({
      selector: 'app-reactive-rigist',
      templateUrl: './reactive-rigist.component.html',
      styleUrls: ['./reactive-rigist.component.css']
    })
    export class ReactiveRigistComponent implements OnInit {
      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};
      }
    
    //自定义方法
      equalValidator(group:FormGroup):any {
        let pwd:FormControl = group.get("pwd") as FormControl;
        let pconfirm:FormControl = group.get("pconfirm") as FormControl;
        let valid:boolean = (pwd.value === pconfirm.value);
        console.log("密码校验结果:"+valid);
        // 当校验通过时返回null,当校验不通过的时候返回{equal : true}
        return valid ? null : {equal : true};
      }
    
    
      myFormGroup:FormGroup;
    
      constructor(fb:FormBuilder) { 
        this.myFormGroup = fb.group({
          username:['',[Validators.required,Validators.minLength(6)]],
          mobile:['',this.mobileValidator],
          passwordGroup:fb.group({
            pwd:[''],
            pconfirm:['']
          // 加入声明,是一个对象
          },{validator:this.equalValidator})
        })
       }
      mySubmit(){
        let isValid:boolean = this.myFormGroup.get("username").valid;
    
        console.log("username的校验结果"+isValid);
        let errors:any = this.myFormGroup.get("username").errors;
    
        console.log("username的错误信息是"+JSON.stringify(errors));
        console.log(this.myFormGroup.value);
      }
      ngOnInit() {
      }
    
    }
    

    4、将校验器单独放到一个文件中,然后用export的方式暴露出去

    ·1.在app目录下新建一个文件夹

    53.png

    2.将刚刚定义的方法放置到validators.ts中

    
    //引入文件
    import { FormGroup,FormControl } from '@angular/forms';
    
    // 注意:此时这两个不再是一个TypeScript方法了,而是全局的一个函数
    // 要用function来声明
    
    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 equalValidator(group:FormGroup):any {
        let pwd:FormControl = group.get("pwd") as FormControl;
        let pconfirm:FormControl = group.get("pconfirm") as FormControl;
        let valid:boolean = (pwd.value === pconfirm.value);
        console.log("密码校验结果:"+valid);
        // 当校验通过时返回null,当校验不通过的时候返回{equal : true}
        return valid ? null : {equal : true};
      }
    
    

    3.在组件中引入这两个全局的方法

    import { Component, OnInit} from '@angular/core';
    import { FormGroup,FormControl,FormBuilder,Validators } from '@angular/forms';
    
    //引入文件
    import {mobileValidator,equalValidator} from '../validator/validators';
    @Component({
      selector: 'app-reactive-rigist',
      templateUrl: './reactive-rigist.component.html',
      styleUrls: ['./reactive-rigist.component.css']
    })
    export class ReactiveRigistComponent implements OnInit {
    
      myFormGroup:FormGroup;
      
      constructor(fb:FormBuilder) { 
        this.myFormGroup = fb.group({
          username:['',[Validators.required,Validators.minLength(6)]],
    
          //此次修改
          mobile:['',mobileValidator],
          passwordGroup:fb.group({  
            pwd:[''],
            pconfirm:['']
    
            // 此处修改
          },{validator:equalValidator})
        })
       }
      mySubmit(){
        let isValid:boolean = this.myFormGroup.get("username").valid;
        console.log("username的校验结果"+isValid);
        let errors:any = this.myFormGroup.get("username").errors;
        console.log("username的错误信息是"+JSON.stringify(errors));
        console.log(this.myFormGroup.value);
      }
      ngOnInit() {
      }
    
    }
    
    

    4.结果是相同的

    5、用.myFormGroup的valid属性来判断整个表单中所有的值是否是合法的

    1.修改代码

    mySubmit(){
    
        if(this.myFormGroup.valid) {
          //只有合法时才打印模型信息
          console.log(this.myFormGroup.value);
        }else {
          console.log("校验未通过");
        }
    
      }
    

    2.结果

    54.png

    6、校验不通过时,显示错误信息给用户

    1.修改模版

    <form [formGroup]="myFormGroup">
        <p>用户名:<input type="text" formControlName="username"></p>
        <!-- 新增校验信息 -->
        <!-- 当校验不通过时返回true,所以取反 -->
        <div [hidden]="!myFormGroup.hasError('required','username')">
            用户名是必填项
        </div>
        <div [hidden]="!myFormGroup.hasError('minlength','username')">
          用户名最小长度是6位
        </div>
        <p>手机号:<input type="text" formControlName="mobile"></p>
        <div [hidden]="!myFormGroup.hasError('mymobile','mobile')">
          请输入正确的手机号
        </div>
        <div formGroupName="passwordGroup">
            <p>密码:<input type="password" formControlName="pwd"></p>
            <p>确认密码:<input type="password" formControlName="pconfirm"></p>
        </div>
        <div [hidden]="!myFormGroup.hasError('myequal','passwordGroup')">
          密码输入不一致
        </div>
        <button type="submit" (click)="mySubmit()">提交</button>
    </form>
    

    2.结果

    55.png 56.png 57.png

    7、在检验器中写错误信息

    1.修改validators.ts

    export function equalValidator(group:FormGroup):any {
        let pwd:FormControl = group.get("pwd") as FormControl;
        let pconfirm:FormControl = group.get("pconfirm") as FormControl;
        let valid:boolean = (pwd.value === pconfirm.value);
        console.log("密码校验结果:"+valid);
        // return valid ? null : {myequal : true};
        // 在此处添加错误信息
        return valid ? null : {myequal : {errorInfo:"密码输入不一致"}};
    
      }
    
    

    2.修改模板

    <div formGroupName="passwordGroup">
            <p>密码:<input type="password" formControlName="pwd"></p>
            <!-- 在嵌套在formGroup内的校验,要写成数组['passwordGroup','pwd'] -->
            <div [hidden]="!myFormGroup.hasError('minlength',['passwordGroup','pwd'])">
                密码最少6位
            </div>
            <p>确认密码:<input type="password" formControlName="pconfirm"></p>
        </div>
        <div [hidden]="!myFormGroup.hasError('myequal','passwordGroup')">
            <!-- 此处修改为 -->
            {{myFormGroup.getError('myequal','passwordGroup')?.errorInfo}}
        </div>
    

    3.结果相同

    8、异步校验器

    将mobile检验器改为异步校验器
    1.修改validators.ts

    import{ Observable } from "rxjs";
    // 异步校验器
      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);
        // 将返回值放到一个流里面返回
        return Observable.of( valid ? null : {mymobile : true}).delay(5000);
      }
    

    2.修改reactive-rigist.component.ts

          mobile:['',mobileValidator,mobileAsyncValidator]
    
    

    3.修改模版
    添加

    <div>
        {{myFormGroup.status}}
    </div>
    

    4.结果

    58.png 59.png

    5秒后


    60.png

    <5>状态字段

    包括:touched和untouched 、 pristine和dirty 、 pending
    touched和untouched:
    用来判断用户是否访问过这个字段,也就是这个字段是否获取过焦点。若获取过焦点,则touched是true,untouched 是false。

    <p>用户名:<input type="text" formControlName="username"></p>
        <!-- 当username通过校验,或者状态是untouched时隐藏校验信息 -->
        <div [hidden]="myFormGroup.get('username').valid ||myFormGroup.get('username').untouched">
            <div [hidden]="!myFormGroup.hasError('required','username')">
                用户名是必填项
            </div>
            <div [hidden]="!myFormGroup.hasError('minlength','username')">
                用户名最小长度是6位
            </div>
        </div>
    

    pristine和dirty
    如果一个字段的值从来没被改变过,那么pristine为true,dirty为false。

    <!-- moblie通过校验或者值从来没被修改过,隐藏错误信息 -->
        <div[hidden]="myFormGroup.get('mobile').valid ||myFormGroup.get('mobile').pristine">
            <div [hidden]="!myFormGroup.hasError('mymobile','mobile')">
                请输入正确的手机号
            </div>
        </div>
    

    pending
    当一个字段正处于异步检验时,pending为true

    <div [hidden]="!myFormGroup.get('mobile').pending">
            正在校验手机号合法性
    </div>
    

    注意
    针对所有的字段,angular会自动根据字段的状态来为它添加一些样式。

    61.png
    .myError {
        border: 1px solid red;
    }
    
        <!-- 当这个字段无效且状态为touched时,增加myError类 -->
    <p>用户名:<input [class.myError]="myFormGroup.get('username').invalid && myFormGroup.get('username').touched" type="text" formControlName="username"></p>
    
    62.png

    <6>模版式表单校验

    1、生成两个指令
    指令可以被看成是一个没有模版的component,指令是作为属性来用的。

    ng g directive directives/moblieValidator
    
    ng g directive directives/equalValidator
    
    63.png

    相关文章

      网友评论

        本文标题:angular4 (5)表单处理

        本文链接:https://www.haomeiwen.com/subject/atraeftx.html