Angular表單創(chuàng)建和校驗(yàn)

Angular中提供了模板驅(qū)動表單和響應(yīng)式表單。
相對來做,模板驅(qū)動表單使用更加簡單,只需要在表單外圍添加#myForm="ngForm"
指令,給每個(gè)表單項(xiàng)添加ngModel指令和name屬性,然后就可以通過myform.value獲取到表單中所有的值;

一、模板驅(qū)動表單

1、基礎(chǔ)用法

創(chuàng)建模板驅(qū)動表單需要3個(gè)步驟

1、添加#myForm="ngForm"
2、在每個(gè)input表單項(xiàng)上添加ngModel指令和name屬性
3、在app.module.ts中引入FormsModule

import { FormsModule }   from '@angular/forms';
@NgModule(
{
  imports:[FormsModule]
}
)
  <form #myForm="ngForm">
    <ion-item>
      <ion-label>標(biāo)題:</ion-label>
      <ion-input type="text" name="title" ngModel></ion-input>
    </ion-item>
    <ion-item>
      <ion-label>子標(biāo)題:</ion-label>
      <ion-input type="text" name="subtitle" ngModel></ion-input>
    </ion-item>
  </form>
  {{myForm.value|json}}
//{{myForm.value.title|json}}取標(biāo)題的值

效果:


1.gif

2、給每個(gè)表單項(xiàng)單獨(dú)定義數(shù)據(jù)模型

給每個(gè)input表單在name="title" ngModel基礎(chǔ)上,添加#mytitle="ngModel",把本表單數(shù)據(jù)綁定到mytitle數(shù)據(jù)模型上??梢酝ㄟ^{{mytitle.value}}直接獲取數(shù)據(jù)。

  <form #myForm="ngForm">
    <ion-item>
      <ion-label>標(biāo)題:</ion-label>
      <ion-input type="text" name="title" ngModel #mytitle="ngModel"></ion-input>
    </ion-item>
    <ion-item>
      <ion-label>子標(biāo)題:</ion-label>
      <ion-input type="text" name="subtitle" ngModel></ion-input>
    </ion-item>
  </form>
  {{myForm.value|json}} <br>
  {{mytitle.value}}
2.gif

3、ngModelGroup使用

將需要?dú)w納到一個(gè)數(shù)據(jù)模型中的所有表單,放到一個(gè)ngModelGroup指令中去

  <form #myForm="ngForm">
    <ion-item>
      <ion-label>標(biāo)題:</ion-label>
      <ion-input type="text" name="title" ngModel></ion-input>
    </ion-item>
    <ion-item>
      <ion-label>子標(biāo)題:</ion-label>
      <ion-input type="text" name="subtitle" ngModel></ion-input>
    </ion-item>
    <div ngModelGroup="passwordInfo">
      <ion-item>
        <ion-label>密碼:</ion-label>
        <ion-input type="text" name="password" ngModel></ion-input>
      </ion-item>
      <ion-item>
        <ion-label>確認(rèn)密碼:</ion-label>
        <ion-input type="text" name="password2" ngModel></ion-input>
      </ion-item>
    </div>
  </form>
  {{myForm.value|json}} 
3.gif

二、響應(yīng)式表單

1、創(chuàng)建

響應(yīng)式表單有三個(gè)表單類,F(xiàn)ormGroup、FormControl、FormArray,F(xiàn)ormGroup可以用來嵌套。ionic3中創(chuàng)建時(shí),不需要在app.module.ts中引入ReactiveFormModule。不需要在app.module中引用@angular/forms模塊,因?yàn)樵赼pp.module中已經(jīng)引入了@angular/platform-browser模塊,而在@angular/platform-browser模塊中又導(dǎo)出了 @angular/forms 。

  <form [formGroup]="myform" (ngSubmit)="save()">
    <ion-item>
      <ion-label>標(biāo)題:</ion-label>
      <ion-input type="text" name="title" formControlName="title"></ion-input>
    </ion-item>
    <div formArrayName="emails">
      <ion-item *ngFor="let item of myform.get('emails').controls;let i=index;">
        <ion-label>郵箱:</ion-label>
        <ion-input type="text" [formControlName]="i"></ion-input>
      </ion-item>
    </div>
    <div formGroupName="passwordInfo">
      <ion-item>
        <ion-label>密碼:</ion-label>
        <ion-input type="text" formControlName="password1"></ion-input>
      </ion-item>
      <ion-item>
        <ion-label>確認(rèn)密碼:</ion-label>
        <ion-input type="text" formControlName="password2"></ion-input>
      </ion-item>
    </div>
    <button ion-button type="submit" >保存</button>
  </form>
import { FormGroup, FormControl, FormArray } from '@angular/forms';
import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
@IonicPage(
  { name: "my" }
)
@Component({
  selector: 'page-my',
  templateUrl: 'my.html',
})
export class MyPage {

  myform: FormGroup;
  constructor(
    public navCtrl: NavController,
    public navParams: NavParams
  ) {
    this.myform = new FormGroup({
      title: new FormControl(),
      emails: new FormArray([
        new FormControl(),
        new FormControl()
      ]),
      passwordInfo: new FormGroup({
        password1: new FormControl(),
        password2: new FormControl()
      })
    });
  }

  save() {
    console.log(this.myform.value);
  }

}

效果:


image.png

2、使用FormBuilder簡化創(chuàng)建代碼

只需要修改my.ts中代碼

import { FormGroup, FormControl, FormArray, FormBuilder } from '@angular/forms';
import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
@IonicPage(
  { name: "my" }
)
@Component({
  selector: 'page-my',
  templateUrl: 'my.html',
})
export class MyPage {
  myform: FormGroup;
  constructor(
    public navCtrl: NavController,
    public navParams: NavParams
  ) {

    let fb: FormBuilder = new FormBuilder();
    this.myform = fb.group({
      title: [""],
      emails: fb.array([
        "", ""
      ]),
      passwordInfo: fb.group({
        password1: [""],
        password2: [""]
      })
    });
  }

  save() {
    console.log(this.myform.value);
  }
}

三、響應(yīng)式表單的校驗(yàn)

在創(chuàng)建表單時(shí),推薦直接使用響應(yīng)式表單,因?yàn)樵谑褂肍ormBuilder創(chuàng)建表單模型的時(shí)候,可以直接提供本地校驗(yàn)和異步校驗(yàn)。
本地校驗(yàn)可以是系統(tǒng)自帶的一些校驗(yàn)(min、max、required、minLength、maxLength、requiredTrue、pattern、nullValidator),也可以是自定義校驗(yàn)器。
異步校驗(yàn)是返回一個(gè)流或者一個(gè)可觀察的promise對象。
下面例子戰(zhàn)士了本地校驗(yàn)的方法:

my.html代碼:

<ion-header>
  <ion-navbar>
    <ion-title>my</ion-title>
  </ion-navbar>
</ion-header>
<ion-content padding>
  <ion-list>
    <form [formGroup]="myform" (ngSubmit)="save()">
      <ion-item>
        <ion-label>標(biāo)題:</ion-label>
        <ion-input type="text" name="title" formControlName="title"></ion-input>
      </ion-item>
      <ion-item>
        <ion-label>手機(jī):</ion-label>
        <ion-input type="text" name="mobile" formControlName="mobile"></ion-input>
      </ion-item>
      <div formArrayName="emails">
        <ion-item *ngFor="let item of myform.get('emails').controls;let i=index;">
          <ion-label>郵箱:</ion-label>
          <ion-input type="text" [formControlName]="i"></ion-input>
        </ion-item>
      </div>
      <div formGroupName="passwordInfo">
        <ion-item>
          <ion-label>密碼:</ion-label>
          <ion-input type="text" formControlName="password1"></ion-input>
        </ion-item>
        <ion-item>
          <ion-label>確認(rèn)密碼:</ion-label>
          <ion-input type="text" formControlName="password2"></ion-input>
        </ion-item>
      </div>
      <button ion-button type="submit">保存</button>
    </form>
  </ion-list>
</ion-content>

my.ts方法:

import { FormGroup, FormBuilder, Validators, FormControl, AbstractControl } from '@angular/forms';
import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
@IonicPage(
  { name: "my" }
)
@Component({
  selector: 'page-my',
  templateUrl: 'my.html',
})
export class MyPage {
  myform: FormGroup;
  constructor(
    public navCtrl: NavController,
    public navParams: NavParams,
    public fb: FormBuilder
  ) {
    this.myform = this.fb.group({
      title: ["", [Validators.required, Validators.minLength(3)]],
      mobile: ["", [this.mobileValidator]],
      emails: this.fb.array(["", ""]),
      passwordInfo: this.fb.group({
        password1: [""],
        password2: [""]
      }, { validator: this.passwordValidator })//子FormGroup數(shù)據(jù)校驗(yàn)必須是一個(gè){validator:***}形式的參數(shù)
    });
  }
  //自定義校驗(yàn)器,參數(shù)必須是AbstractControl類型,此類型是FormControll、FormGroup、FormArray的父類。返回值是一個(gè)json,key必須是string類型。
  // nameValidator(param: AbstractControl): { [key: string]: any } {
  //   return null;
  // }
  mobileValidator(mobile: FormControl): any {
    let value = (mobile.value || "") + "";
    let myreg = /^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\d{8}$/;
    let valid = myreg.test(value);
    return valid ? null : { mobile: true };
  }
  passwordValidator(passwordInfo: FormGroup): any {
    let password1 = passwordInfo.get("password1").value;
    let password2 = passwordInfo.get("password2").value;
    let valid = (password1 == password2);
    return valid ? null : { password: true };
  }
  save() {
    let title = this.myform.get("title");
    let mobile = this.myform.get("mobile");
    let passwordInfo = this.myform.get("passwordInfo");
    if (!this.myform.valid) {
      if (title.hasError("required")) {
        alert("標(biāo)題必填");
        return;
      }
      //*******************注意hasError中參數(shù)必須都小寫********************
      if (title.hasError("minlength")) {
        alert("標(biāo)題最小3位");
        return;
      }
      if (mobile.hasError("mobile")) {
        alert("手機(jī)格式不對");
        return
      }
      if (passwordInfo.hasError("password")) {
        alert("兩次密碼輸入不一樣");
        return
      }
    }
  }
}

上面自定義了兩個(gè)校驗(yàn)器,mobileValidator和passwordValidator,可以對手機(jī)號碼和密碼進(jìn)行校驗(yàn)。
如果當(dāng)myform.vlide==true,則說明整個(gè)表單模型沒有錯(cuò)誤。
要獲取某一個(gè)表單控件的校驗(yàn)信息:this.myform.get("title").errors
獲取某一個(gè)表單控件某一種校驗(yàn)是否通過:this.myform.get("title").hasError("minlength")。注意這里的參數(shù)一般是小寫,可以答應(yīng)errors結(jié)果看下,參數(shù)就是里面的key的值。

大型項(xiàng)目一般不會把自定義校驗(yàn)放在具體頁面里面,而是建立一個(gè)校驗(yàn)ts文件,這些校驗(yàn)函數(shù)都放在校驗(yàn)文件里面。新建一個(gè)validators.ts,注意當(dāng)把類中方法改成獨(dú)立函數(shù)的時(shí)候,需要在前面加上function,如果是公共函數(shù),則要加上export function。

validators.ts文件

import { FormGroup, FormControl } from '@angular/forms';

export function mobileValidator(mobile: FormControl): any {
    let value = (mobile.value || "") + "";
    let myreg = /^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\d{8}$/;
    let valid = myreg.test(value);
    return valid ? null : { mobile: true };
}
export function passwordValidator(passwordInfo: FormGroup): any {
    let password1 = passwordInfo.get("password1").value;
    let password2 = passwordInfo.get("password2").value;
    let valid = (password1 == password2);
    return valid ? null : { password: true };
}

my.ts文件修改:

import { mobileValidator, passwordValidator } from '../validators'//**************頭部需要引用*************
  constructor(
    ......
  ) {
    this.myform = this.fb.group({
      title: ["", [Validators.required, Validators.minLength(3)]],
      mobile: ["", [mobileValidator]],//***********直接寫函數(shù)名稱**********
      emails: this.fb.array(["", ""]),
      passwordInfo: this.fb.group({
        password1: [""],
        password2: [""]
      }, { validator: passwordValidator })//***********直接寫函數(shù)名稱**********
    });
  }

四、響應(yīng)式編程

1、簡單的響應(yīng)式編程

當(dāng)我們使用ngModel綁定數(shù)據(jù)模型時(shí),就已經(jīng)實(shí)現(xiàn)了簡單的響應(yīng)式編程。
html模板代碼

<ion-input type="text" [(ngModel)]="title"></ion-input>
{{title}}

當(dāng)在輸入框輸入文字時(shí),頁面上會動態(tài)輸出文字內(nèi)容。

2、數(shù)據(jù)流響應(yīng)式編程

使用ngModel方式綁定的數(shù)據(jù)模型,每次keyup都會直接把數(shù)據(jù)輸出。假如我們需要每次輸入500ms后才輸出,這時(shí)候就需要把輸入這個(gè)事件流做好監(jiān)聽。
html模板代碼:

<ion-input type="text" name="title2" [formControl]="title2"></ion-input>

ts文件:

import "rxjs";
title2: FormControl = new FormControl();
  constructor(){
    this.title2.valueChanges
      .debounceTime(500)
      .subscribe(
      (data) => {
        console.log(data);
      }
      )
} 

angular教程說需要在app.module.ts中引入ReactiveFormsModule,但是在ionic3實(shí)際使用中,不加ReactiveFormsModule也可以正常運(yùn)行。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容