angular4 (5)表單處理

<1>angular表單API

40.png

不同點

41.png

注意
要使用angular表單柠偶,要在app.module.ts中引入相應(yīng)的模塊
模版式表單:FormsModule
響應(yīng)式表單:ReactiveFormsModule

42.png

<2>模版式表單

使用模版式表單時位隶,只能使用指令來定義數(shù)據(jù)模型。

(1)NgForm

用來代表整個表單树枫,在angular項目中,它會自動添加到每個form標(biāo)簽上藤树。
示例:
1.新建一個組件

ng g component templateForm

2.修改template-form.component.html

<form action="/action" method="POST">
  <p>用戶名:<input type="text"></p>
  <p>手機(jī)號:<input type="text"></p>
  <p>密碼:<input type="password"></p>
  <p>確認(rèn)密碼:<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表示此表達(dá)不讓angular接管 -->
<form action="/action" method="POST" ngNoForm>
  <p>用戶名:<input type="text"></p>
  <p>手機(jī)號:<input type="text"></p>
  <p>密碼:<input type="password"></p>
  <p>確認(rèn)密碼:<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>手機(jī)號:<input type="text"></p>
  <p>密碼:<input type="password"></p>
  <p>確認(rèn)密碼:<input type="password"></p>
  <button type="submit">提交</button>
</form>
<!-- 下面通過這個模板變量來訪問ngForm對象的屬性 -->
<!-- value是一個js對象斋陪,它保存了當(dāng)前表單里面的值 -->
{{myForm.value | json}}

2.結(jié)果

44.png

(2)NgModel

ngModel指令代表表單中的一個字段朽褪,這個指令會隱式的創(chuàng)建一個FormControl的實例,來代表字段的數(shù)據(jù)模型无虚,并用這個FormControl類型的對象來存儲字段的值缔赠。
在上面例子的json中,當(dāng)在表單中輸入值時沒有加到j(luò)son中顯示的原因是友题,那些input標(biāo)簽并未綁定ngModel指令嗤堰。
注意
在ngForm中使用ngModel不需要像普通的數(shù)據(jù)雙向綁定那樣用[(ngModel)]的方式,直接寫ngModel即可
ngModel也可以使用模版變量來獲取它的值
示例
1.

<!-- 聲明一個模板變量#myForm -->
<form #myForm="ngForm" action="/action" method="POST">
  <!-- 給用戶名綁定ngModel,并且聲明一個模板變量#user -->
  <!-- 注意度宦,一定要給標(biāo)簽聲明一個name屬性 -->
  <p>用戶名:<input #user="ngModel" ngModel name="username" type="text"></p>
  <p>手機(jī)號:<input type="text"></p>
  <p>密碼:<input type="password"></p>
  <p>確認(rèn)密碼:<input type="password"></p>
  <button type="submit">提交</button>
</form>
<!-- 下面通過這個模板變量來訪問ngForm對象的屬性 -->
<!-- value是一個js對象踢匣,它保存了當(dāng)前表單里面的值 -->
{{myForm.value | json}}

<!-- 用#user模板變量來獲取用戶名的值 -->
{{username.value}}

2.結(jié)果
此時再次輸入用戶名時就會實時反映到下面的json中

45.png

當(dāng)應(yīng)用為單頁應(yīng)用并不需要跳轉(zhuǎn)網(wǎng)頁時告匠,往往用ngSubmit來替代form標(biāo)簽的提交作用
示例
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>手機(jī)號:<input type="text"></p>
  <p>密碼:<input type="password"></p>
  <p>確認(rèn)密碼:<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

代表的是表單的一部分,它允許你將一些表單字段組織在一起离唬,形成一個更清晰的層次關(guān)系凫海,與ngForm指令類似,ngModelGroup指令也會創(chuàng)建一個FormGroup類的一個實例男娄,這個實例會在ngForm對象的value屬性中表現(xiàn)為一個嵌套的對象,所以說ngModelGroup的子屬性都會變?yōu)檫@個嵌套對象的子屬性
示例
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>手機(jī)號:<input type="text"></p>
  </div>
  <p>密碼:<input type="password"></p>
  <p>確認(rèn)密碼:<input type="password"></p>
  <button type="submit">提交</button>
</form>
<!-- 下面通過這個模板變量來訪問ngForm對象的屬性 -->
<!-- value是一個js對象漾稀,它保存了當(dāng)前表單里面的值 -->
{{myForm.value | json}}

<!-- 用#user模板變量來獲取用戶名的值 -->
{{username.value}}

2.結(jié)果
username就被嵌套在userInfo中成為了userInfo的一個屬性模闲。

46.png

(4)重構(gòu)用戶注冊表單的案例

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>手機(jī)號:<input ngModel name="phone" type="text"></p>
  </div>
  <!-- 嵌套一個ngModelGroup -->
  <div ngModelGroup="passwordsGroup">
    <p>密碼:<input ngModel name="password" type="password"></p>
    <p>確認(rèn)密碼:<input ngModel name="pconfirm" type="password"></p>
  </div>
  <button type="submit">提交</button>
</form>

2.結(jié)果
當(dāng)輸入結(jié)束,點擊提交時

47.png

<3>響應(yīng)式表單

與模版式表單不同崭捍,創(chuàng)建一個響應(yīng)式表單需要兩步尸折,首先需要編碼來創(chuàng)建一個數(shù)據(jù)模型,然后需要使用些指令將模版中的html元素連接到這個數(shù)據(jù)模型上殷蛇。

1实夹、數(shù)據(jù)模型

是指用來保存表單數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu),簡稱模型粒梦。它由定義在angular的forms模塊中的三個類組成亮航。分別是:FormCotrol,F(xiàn)ormGroup匀们,F(xiàn)ormArray

(1)FormCotrol:是構(gòu)成表單的基本單位缴淋,通常情況下它用來代表一個input元素,它也可以用來代表一個更復(fù)雜的UI組件泄朴,比如說日歷重抖、下拉選擇塊等。FormCotrol保存著與其關(guān)聯(lián)的html元素當(dāng)前的值以及元素的校驗狀態(tài)祖灰,還有元素是否被修改過等信息钟沛。

如何創(chuàng)建一個FormCotrol,示例:

//其中FormCotrol接收的參數(shù)aaa是username的初始值
username:FormCotrol = new FormCotrol("aaa");

(2)FormGroup:FormGroup既可以代表表單的一部分也可以用于代表整個表單局扶,它是多個FormCotrol的集合恨统,F(xiàn)ormGroup將多個FormCotrol的值和狀態(tài)聚合在一起。如果一個FormCotrol是無效的详民,那么整個FormGroup都是無效的延欠。
優(yōu)點:在管理表單中多個相關(guān)聯(lián)的字段時,使用FormGroup是很方便的沈跨,比如一個日期范圍由捎,有起始和終止日期兩個input,這兩個input可以放到一個FormGroup中饿凛,當(dāng)其中一個任何一個字段的值無效時都會顯示一個錯誤信息狞玛。

如何創(chuàng)建一個FormGroup软驰,示例:

//FormGroup的構(gòu)造函數(shù)需要一個對象
formModel:FormGroup = new FormGroup({
    fromDate: new FormCotrol(),
    toDate: new FormCotrol()
});

(3)FormArray:FormArray和FormGroup是類似的,但是它有一個額外的長度屬性心肪,一般來說FormGroup用來代表整個表單或者表單字段的一個固定的子集锭亏。而FormArray通常用來代表一個可以增長的字段集合。

如何創(chuàng)建一個FormArray硬鞍,示例:

//FormArray的構(gòu)造函數(shù)是一個數(shù)組
emails:FormArray = new FormArray([
    new FormCotrol("a@qq.com"),
    new FormCotrol("b@qq.com")
]);

2慧瘤、響應(yīng)式表單指令

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';

// 引入響應(yīng)式表單
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標(biāo)簽的formGroup對象來代表整個表單
  用formGroup屬性綁定到后臺定義的myFormModel
  這樣就把整個表單的處理方式變成了響應(yīng)式表單的處理方式
 -->
 <!-- 2.提交方法 -->
<form [formGroup] = "myFormModel" (submit)="mySubmit()">
  <!-- 3.用formGroupName來連接一個formGroup -->
  <div formGroupName="dateRange">
    <!-- 
      4.formControlName必須聲明在formGroup內(nèi)桦沉,來連接formGroup中的formControl和頁面上的dom元素
     -->
    起始日期:<input type="date" formControlName="formDate"><br><br>
    截至日期:<input type="date"  formControlName="toDate">
  </div>
  <!-- 5.formArrayName也必須放在formGroup范圍內(nèi) -->
  <div>
    <ul formArrayName="emails">
      <!-- 6.因為FormArray是用下標(biāo)來顯示每條數(shù)據(jù)的每瞒,所以一般配合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的數(shù)據(jù)模型里 -->
  <input type="text" formControlName = "username2">
</form>
<br>
<!-- 
  8.formControl指令不能放在formGroup的內(nèi)部
    這個username不在formGroup里,所以點擊保存不會打印出來
 -->
<input type="text" [formControl] = "username">

4.結(jié)果

49.png

3纯露、響應(yīng)式表單重構(gòu)用戶注冊表

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';

//引入響應(yīng)式表單
import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
  declarations: [
    AppComponent,
    ReactiveRigistComponent
  ],
  imports: [
    BrowserModule,
    //引入響應(yīng)式表單
    ReactiveFormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

2.修改reactive-rigist.component.html

<form [formGroup] = "myFormGroup">
  <p>用戶名:<input type="text" formControlName = "username"></p>
  <p>手機(jī)號:<input type="text" formControlName = "mobile"></p>
  <div formGroupName = "passwordGroup">
    <p>密碼:<input type="password" formControlName = "pwd"></p>
    <p>確認(rèn)密碼:<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.結(jié)果

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的校驗器

校驗器就是一個普通的方法苔埋,該方法接收一個參數(shù)懦砂,參數(shù)類型必須為AbstractControl,必須要有一個返回值组橄,返回值可以是任意結(jié)構(gòu)的一個對象荞膘,這個對象的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({
      // 第一個是默認(rèn)值玉工,第二個是校驗器
      // 單個校驗器的寫法
      // 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的校驗結(jié)果"+isValid);
    let errors:any = this.myFormGroup.get("username").errors;

    console.log("username的錯誤信息是"+JSON.stringify(errors));
    console.log(this.myFormGroup.value);
  }
  ngOnInit() {
  }

}

結(jié)果

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 {

//自定義手機(jī)號校驗器
  mobileValidator(control:FormControl):any {
    // 手機(jī)號正則表達(dá)式
    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的校驗結(jié)果是:"+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的校驗結(jié)果"+isValid);
    let errors:any = this.myFormGroup.get("username").errors;

    console.log("username的錯誤信息是"+JSON.stringify(errors));
    console.log(this.myFormGroup.value);
  }
  ngOnInit() {
  }

}

2、結(jié)果

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的校驗結(jié)果是:"+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("密碼校驗結(jié)果:"+valid);
    // 當(dāng)校驗通過時返回null,當(dāng)校驗不通過的時候返回{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的校驗結(jié)果"+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方法了,而是全局的一個函數(shù)
// 要用function來聲明

export function mobileValidator(control:FormControl):any {
    // 手機(jī)號正則表達(dá)式
    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的校驗結(jié)果是:"+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("密碼校驗結(jié)果:"+valid);
    // 當(dāng)校驗通過時返回null,當(dāng)校驗不通過的時候返回{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的校驗結(jié)果"+isValid);
    let errors:any = this.myFormGroup.get("username").errors;
    console.log("username的錯誤信息是"+JSON.stringify(errors));
    console.log(this.myFormGroup.value);
  }
  ngOnInit() {
  }

}

4.結(jié)果是相同的

5翰萨、用.myFormGroup的valid屬性來判斷整個表單中所有的值是否是合法的

1.修改代碼

mySubmit(){

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

  }

2.結(jié)果

54.png

6脏答、校驗不通過時,顯示錯誤信息給用戶

1.修改模版

<form [formGroup]="myFormGroup">
    <p>用戶名:<input type="text" formControlName="username"></p>
    <!-- 新增校驗信息 -->
    <!-- 當(dāng)校驗不通過時返回true,所以取反 -->
    <div [hidden]="!myFormGroup.hasError('required','username')">
        用戶名是必填項
    </div>
    <div [hidden]="!myFormGroup.hasError('minlength','username')">
      用戶名最小長度是6位
    </div>
    <p>手機(jī)號:<input type="text" formControlName="mobile"></p>
    <div [hidden]="!myFormGroup.hasError('mymobile','mobile')">
      請輸入正確的手機(jī)號
    </div>
    <div formGroupName="passwordGroup">
        <p>密碼:<input type="password" formControlName="pwd"></p>
        <p>確認(rèn)密碼:<input type="password" formControlName="pconfirm"></p>
    </div>
    <div [hidden]="!myFormGroup.hasError('myequal','passwordGroup')">
      密碼輸入不一致
    </div>
    <button type="submit" (click)="mySubmit()">提交</button>
</form>

2.結(jié)果

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("密碼校驗結(jié)果:"+valid);
    // return valid ? null : {myequal : true};
    // 在此處添加錯誤信息
    return valid ? null : {myequal : {errorInfo:"密碼輸入不一致"}};

  }

2.修改模板

<div formGroupName="passwordGroup">
        <p>密碼:<input type="password" formControlName="pwd"></p>
        <!-- 在嵌套在formGroup內(nèi)的校驗阿蝶,要寫成數(shù)組['passwordGroup','pwd'] -->
        <div [hidden]="!myFormGroup.hasError('minlength',['passwordGroup','pwd'])">
            密碼最少6位
        </div>
        <p>確認(rèn)密碼:<input type="password" formControlName="pconfirm"></p>
    </div>
    <div [hidden]="!myFormGroup.hasError('myequal','passwordGroup')">
        <!-- 此處修改為 -->
        {{myFormGroup.getError('myequal','passwordGroup')?.errorInfo}}
    </div>

3.結(jié)果相同

8、異步校驗器

將mobile檢驗器改為異步校驗器
1.修改validators.ts

import{ Observable } from "rxjs";
// 異步校驗器
  export function mobileAsyncValidator(control:FormControl):any {
    // 手機(jī)號正則表達(dá)式
    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的校驗結(jié)果是:"+valid);
    // 將返回值放到一個流里面返回
    return Observable.of( valid ? null : {mymobile : true}).delay(5000);
  }

2.修改reactive-rigist.component.ts

      mobile:['',mobileValidator,mobileAsyncValidator]

3.修改模版
添加

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

4.結(jié)果

58.png

59.png

5秒后


60.png

<5>狀態(tài)字段

包括:touched和untouched 黄绩、 pristine和dirty 羡洁、 pending
touched和untouched:
用來判斷用戶是否訪問過這個字段,也就是這個字段是否獲取過焦點爽丹。若獲取過焦點筑煮,則touched是true,untouched 是false粤蝎。

<p>用戶名:<input type="text" formControlName="username"></p>
    <!-- 當(dāng)username通過校驗咆瘟,或者狀態(tài)是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')">
            請輸入正確的手機(jī)號
        </div>
    </div>

pending
當(dāng)一個字段正處于異步檢驗時墓懂,pending為true

<div [hidden]="!myFormGroup.get('mobile').pending">
        正在校驗手機(jī)號合法性
</div>

注意
針對所有的字段霉囚,angular會自動根據(jù)字段的狀態(tài)來為它添加一些樣式。

61.png

.myError {
    border: 1px solid red;
}
    <!-- 當(dāng)這個字段無效且狀態(tài)為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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市豆同,隨后出現(xiàn)的幾起案子含鳞,更是在濱河造成了極大的恐慌,老刑警劉巖精居,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件靴姿,死亡現(xiàn)場離奇詭異佛吓,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)淤刃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進(jìn)店門逸贾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來津滞,“玉大人触徐,你說我怎么就攤上這事∨北” “怎么了享郊?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵拂蝎,是天一觀的道長惶室。 經(jīng)常有香客問我皇钞,道長,這世上最難降的妖魔是什么馆里? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任鸠踪,我火速辦了婚禮营密,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘纷捞。我一直安慰自己被去,他們只是感情好惨缆,可當(dāng)我...
    茶點故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布坯墨。 她就那樣靜靜地躺著畅蹂,像睡著了一般荣恐。 火紅的嫁衣襯著肌膚如雪叠穆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天示损,我揣著相機(jī)與錄音检访,去河邊找鬼脆贵。 笑死起暮,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的柏腻。 我是一名探鬼主播系吭,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼村斟,長吁一口氣:“原來是場噩夢啊……” “哼蟆盹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起峰档,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤讥巡,失蹤者是張志新(化名)和其女友劉穎欢顷,沒想到半個月后捉蚤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缆巧,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡陕悬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年捉超,在試婚紗的時候發(fā)現(xiàn)自己被綠了拼岳。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡牛柒,死狀恐怖痊乾,靈堂內(nèi)的尸體忽然破棺而出哪审,到底是詐尸還是另有隱情,我是刑警寧澤滴须,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布扔水,位于F島的核電站魔市,受9級特大地震影響赵哲,放射性物質(zhì)發(fā)生泄漏枫夺。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望毙死。 院中可真熱鬧扼倘,春花似錦再菊、人聲如沸颜曾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽略水。三九已至劝萤,卻和暖如春床嫌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鳖谈。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工蚯姆, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留龄恋,地道東北人郭毕。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓显押,卻偏偏與公主長得像傻挂,于是被迫代替她去往敵國和親金拒。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,870評論 2 361

推薦閱讀更多精彩內(nèi)容