利用angular4和nodejs-express構建一個簡單的網站(七)—用戶註冊之ReactiveForm

這一節對用戶註冊組件進行分析。
用戶註冊組件主要涉及angular4表單的操做。Angular提供了兩種構建表單的技術:響應式表單和模板驅動表單。 這兩項技術都屬於@angular/forms庫,而且共享一組公共的表單控件類。我在用戶註冊組件(regist.component)中使用的是響應式表單(ReactiveFormsModule),要了解更多angular表單的知識,能夠訪問官方文檔,裏面介紹的很詳細。react

註冊組件模板分析

用戶註冊須要用戶名、密碼、郵箱(非必須)三個信息註冊表單組件的模板代碼以下:api

<form [formGroup]="registForm" (ngSubmit)="onSubmit()" novalidate>
    <div class="form-group">
      <label for="name">User name</label>
      <input class="form-control" formControlName="name" id="name" required>
      <div *ngIf="name.invalid && (name.dirty || name.touched)" class="alert alert-danger">
        <div *ngIf="name.errors.required">
          Name is required!
        </div>
        <div *ngIf="name.errors.minlength">
          Name must be at least 4 characters long.
        </div>
        <div *ngIf="name.errors.pattern">
          Name must be composed of letters, numbers
        </div>
      </div>
    </div>
    <div class="form-group">
      <label for="password">Password</label>
      <input class="form-control" formControlName="password" type="password" required id="password" #pass>
      <div *ngIf="password.invalid && (password.dirty || password.touched)" class="alert alert-danger">
        <div *ngIf="password.errors.required">
          Password is required!
        </div>
        <div *ngIf="password.errors.minlength">
          Password must be at least 8 characters long.
        </div>
        <div *ngIf="password.errors.pattern">
          <!--密碼必須由字母、數字、下劃線和減號組成,首字母要求大寫 -->
          Password must be composed of letters, numbers, '_', '-' and Capital letters must be capitalized.
        </div>
      </div>
    </div>
    <div class="from-group">
      <label for="repassword">Re Password</label>
      <input type="password" class="form-control" required id="repassword" (focus)="checkValid()"
       formControlName="repassword">
      <div class="alert alert-danger" *ngIf="repassword.invalid && (repassword.dirty || repassword.touched)">
        <div *ngIf="repassword.errors.required">
          Re password is required!
        </div>
        <div *ngIf="repassword.errors.comparePassword">
          Re password must equal password!
        </div>
      </div>
    </div>
    <div class="form-group email-group">
      <label for="email">Email</label>
      <input class="form-control" formControlName="email" type="email" id="email">
      <div *ngIf="email.invalid &&(email.dirty || email.touched)" class="alert alert-danger">
        <div *ngIf="email.errors.pattern">
          The email address format is incorrect
        </div>
      </div>
    </div>
    <div class="form-group form-btn">
      <button type="submit" class="btn btn-primary" [disabled]="registForm.invalid">Submit</button>
      <button type="button" class="btn btn-light" [disabled]="registForm.pristine" (click)="revert()">Cancel</button>
    </div>
  </form>

導航到regist組件後在name、password、repassword、email中添加相應的信息,點擊Submit按鈕,就會觸發ngSubmit事件,在form標籤中定義處理ngSubmit事件的函數onSubmit(),onSubmit()函數將註冊信息發送到服務器。
novalidate阻止瀏覽器使用原生HTML表單驗證,由於這裏使用了angular的表單驗證。
對於響應式表單須要在模板的form標籤中聲明formGroup(在這裏formGroup聲明爲registForm),還須要在輸入控件(如input、select等)標籤中聲明formControlName。
模板中還有一些關於表單驗證的內容,以下面的代碼:瀏覽器

<div *ngIf="password.invalid && (password.dirty || password.touched)" class="alert alert-danger">
        ...
</div>

在表單狀態爲dirty(髒)狀態和touched(碰過)狀態時若是password爲invalid(不合法,表單控件不合法(invalid)表示未能知足控件的驗證規則),div標識符中的內容將呈現到password控件的下方。違反了不一樣的驗證規則,會呈現不一樣的內容,如在上一段代碼中的div標籤中還包裹着:服務器

<div *ngIf="password.errors.required">
          Password is required!
    </div>

代表在違反了「password.errors.required」規則時,會呈現「Password is required!」內容。
在提交按鈕(Submit)上的標記[disabled]="registForm.invalid",表示當form表單有不符合驗證規則的輸入時,按鈕不能使用。
取消輸入按鈕(Cancel)在控件值未發生變化時(registForm.pristine)不能使用。
模板的基本分析就到這裏,下面咱們來看看ts文件中的組件類。angular4

註冊組件組件類分析

註冊組件的組件類設計內容較多,在這裏分部進行分析。
首先要建立響應式表單並定義表單的認證規則。須要從forms模塊中引入FormBuilder、 FormGroup和Validators類。ide

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

並在構造方法中聲明並初始化這三個類。函數

constructor(
    ...
    private fb: FormBuilder,
    private userSer: UserService,
    private tokenServ: AuthTokenService) {
    ...
  }

下一步利用FormBuilder建立表單。建立一個方法createForm(),用於建立表單,方法中的代碼以下:ui

this.registForm = this.fb.group({
      'name': [this.user.name, [
        Validators.required,
        Validators.minLength(4),
        Validators.pattern(/^[a-z]|[A-Z]|[0-9]$/)]],
      'password': [this.user.password,
      [Validators.required,
      Validators.minLength(8),
      Validators.pattern(/^[A-Z][a-zA-Z0-9_-]+$/)]],
      'email': [this.user.email,
      Validators.pattern(/^([a-zA-Z0-9_\.\-]+)@([a-zA-Z0-9_\.\-]+)\.([a-zA-Z]{2,4})$/)],
      'repassword': [this.user.password, [
        Validators.required]]
    });

registForm是一個FormGroup的實例,關聯模板中的formGroup([formGroup]="registForm"),在類中進行聲明:this

registForm: FormGroup;

利用FormBuilder.group來生成響應式表單,FormBuilder.group是一個用來建立FormGroup的工廠方法,它接受一個對象,對象的鍵和值分別是FormControl的名字和它的定義。在這個對象中對name、password、email、repassword四個FormControl進行了初始化。定義了這四個FormControl的初始值對應User類的對象user的四個同名屬性(repassword對應的是user.password,用於對用戶密碼的重複輸入進行驗證)。user對象也是在類中定義的:設計

user: User = new User(0, '', '', '');

表單驗證

在FormControl的初始化中還定義了驗證規則,這個表單的驗證規則由如下幾種:

  • 必須輸入內容(Validators.required)
  • 最少須要x個字符(Validators.minlength(x))
  • 正則驗證,必須由字母、數字組成 Validators.pattern(/^[a-z]|[A-Z]|[0-9]$/)
  • 正則驗證,必須由字母、數字、下劃線和減號組成,首字母要求大寫 Validators.pattern(/^[A-Z][a-zA-Z0-9_-]+$/)]]
  • 必須符合email格式要求,能夠使用Validators.email,也能夠使用正則驗證。

對FormControl進行驗證,還須要編寫get方法來訪問表單控件:

get name() { return this.registForm.get('name'); }
  get password() { return this.registForm.get('password'); }
  get email() { return this.registForm.get('email'); }
  get repassword() { return this.registForm.get('repassword'); }

這裏還須要自定義一個驗證器,用於驗證repassword輸入的值是否和password的值相同。
自定義驗證器由一個驗證工廠函數構成。代碼以下:

import { AbstractControl,ValidatorFn } from '@angular/forms';

export function passwordEquals(password: string): ValidatorFn {
    return (control: AbstractControl): { [key: string]: any } => {
        const isEquals = (password === control.value);
        return isEquals ? null : { 'comparePassword': control.value };
    }
}

passwordEquals()方法須要傳入一個string類型的參數,返回配置好的驗證器函數。該函數接受一個Angular控制器對象,在控制器的值和參數相同時返回null,不相同時返回驗證錯誤對象,錯誤對象是一個現實控件值的鍵值對。
將自定義驗證器加到表單的repassword屬性上,但由於passwordEquals()的參數須要的是password控件的值,而password控件的值不能在表單建立時拿到,須要在password控件有值後才能拿到。那麼,進行自定義驗證器加載的最好時機就是repassword控件得到焦點的時候。因此,在模板中要加入repassword控件的標籤中加入焦點事件:(focus)="checkValid()",在處理焦點事件的checkValid()函數中,爲repassword加入自定義驗證規則,判斷它的值是否和控件password的值相同:

checkValid() {
    this.repassword.setValidators([Validators.required, passwordEquals(this.pass.nativeElement.value)]);
  }

this.pass是經過在password的<input>組件中聲明一個引用變量#pass後,經過@ViewChild('pass') pass: ElementRef;獲取到password的<input>組件的值。
關於用戶註冊中響應式表單(ReactiveForm)的構建和驗證基本上就是這些了,下一章將要介紹如何向服務器發送註冊信息並導航到下一個模塊。

關於angular表單驗證規則和驗證方法能夠查看官方文檔中的介紹。

相關文章
相關標籤/搜索