首頁  >  文章  >  web前端  >  關於Angular中響應式表單的介紹

關於Angular中響應式表單的介紹

不言
不言原創
2018-07-11 14:57:201806瀏覽

這篇文章主要介紹了關於Angular中響應式表單的介紹,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下

響應式表單是在元件類別中編寫邏輯,驗證規則,這與在範本中完成控制的範本驅動表單不同。響應式表單反應形式是靈活的,可用於處理任何複雜的形式場景。我們編寫更多的元件程式碼和更少的HTML程式碼,讓單元測試更容易。

Form base and interface

Form base

<form novalidate>
  <label>
    <span>Full name</span>
    <input
      type="text"
      name="name"
      placeholder="Your full name">
  </label>
  <p>
    <label>
      <span>Email address</span>
      <input
        type="email"
        name="email"
        placeholder="Your email address">
    </label>
    <label>
      <span>Confirm address</span>
      <input
        type="email"
        name="confirm"
        placeholder="Confirm your email address">
    </label>
  </p>
  <button type="submit">Sign up</button>
</form>

接下來我們要實作的功能如下:

  • 綁定name、 email、confirm 輸入框的值

  • 為所有輸入框新增表單驗證功能

  • 顯示驗證異常訊息

  • ##表單驗證失敗時,不允許進行表單提交

  • 表單提交功能

User interface

// signup.interface.ts
export interface User {
  name: string;
  account: {
    email: string;
    confirm: string;
  }
}

ngModule and reactive forms

在我們繼續深入介紹reactive forms 表單前,我們必須在@NgModule 中導入@angular/forms 庫中的ReactiveFormsModule:

import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
  imports: [
    ...,
    ReactiveFormsModule
  ],
  declarations: [...],
  bootstrap: [...]
})
export class AppModule {}
友情提示:若使用reactive forms,則匯入ReactiveFormsModule;若使用template-driven 表單,則匯入FormsModule。
Reactive approach

我們將基於上面的定義的基礎表單,建立SignupFormComponent :

signup-form.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'signup-form',
  template: `
    <form novalidate>...</form>
  `
})
export class SignupFormComponent {
  constructor() {}
}
這是一個基礎的元件,在我們實現上述功能之前,我們需要先介紹FormControl、FormGroup、FormBuilder 的概念和使用。

FormControl and FormGroup

我們先來介紹一下FormControl 和FormGroup 的概念:

FormControl - 它是一個為單一表單控制項提供支援的類,可用於追蹤控制項的值和驗證狀態,此外還提供了一系列公共API。
使用範例:

ngOnInit() {
  this.myControl = new FormControl('');
}
FormGroup - 包含是一組 FormControl 實例,可用於追蹤 FormControl 群組的值和驗證狀態,此外也提供了一系列公開API。
使用範例:

ngOnInit() {
  this.myGroup = new FormGroup({
    name: new FormControl(''),
    location: new FormControl('')
  });
}
現在我們已經建立了FormControl 和FormGroup 實例,接下來我們來看如何使用:

<form novalidate [formGroup]="myGroup">
  Name: <input type="text" formControlName="name">
  Location: <input type="text" formControlName="location">
</form>
上面範例中,我們必須使用[ formGroup] 綁定我們建立的myGroup 對象,除此之外還要使用formControlName 指令,綁定我們建立的FormControl 控制項。此時的表單結構如下:

FormGroup -> 'myGroup'
    FormControl -> 'name'
    FormControl -> 'location'
Implementing our FormGroup model

signup.interface.ts

export interface User {
  name: string;
  account: {
    email: string;
    confirm: string;
  }
}
與之對應的表單結構如下:

FormGroup -> 'user'
    FormControl -> 'name'
    FormGroup -> 'account'
        FormControl -> 'email'
        FormControl -> 'confirm'
是的,我們可以建立嵌套的FormGroup 集合!讓我們更新一下元件 (不包含初始數據):

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

@Component({...})
export class SignupFormComponent implements OnInit {
  user: FormGroup;
  ngOnInit() {
    this.user = new FormGroup({
      name: new FormControl(''),
      account: new FormGroup({
        email: new FormControl(''),
        confirm: new FormControl('')
      })
    });
  }
}
如果我們想要設定初始數據,我們可以按照上述範例進行設定。通常情況下,我們會透過服務端提供的 API 介面來取得表單的初始資訊。

Binding our FormGroup model

現在我們已經實例化了 FormGroup 模型,是時候綁定到對應的 DOM 元素上了。具體範例如下:

<form novalidate [formGroup]="user">
  <label>
    <span>Full name</span>
    <input
      type="text"
      placeholder="Your full name"
      formControlName="name">
  </label>
  <p formGroupName="account">
    <label>
      <span>Email address</span>
      <input
        type="email"
        placeholder="Your email address"
        formControlName="email">
    </label>
    <label>
      <span>Confirm address</span>
      <input
        type="email"
        placeholder="Confirm your email address"
        formControlName="confirm">
    </label>
  </p>
  <button type="submit">Sign up</button>
</form>
現在FormGroup 與FormControl 物件與DOM 結構的關聯資訊如下:

// JavaScript APIs
FormGroup -> 'user'
    FormControl -> 'name'
    FormGroup -> 'account'
        FormControl -> 'email'
        FormControl -> 'confirm'

// DOM bindings
formGroup -> 'user'
    formControlName -> 'name'
    formGroupName -> 'account'
        formControlName -> 'email'
        formControlName -> 'confirm'
Reactive submit

跟範本驅動的表單一樣,我們可以透過ngSubmit輸出屬性,處理表單的提交邏輯:

<form novalidate (ngSubmit)="onSubmit()" [formGroup]="user">
  ...
</form>
Reactive error validation

接下來我們來為表單新增驗證規則,首先我們需要從@angular/forms 匯入Validators。具體使用範例如下:

ngOnInit() {
  this.user = new FormGroup({
    name: new FormControl('', [Validators.required, Validators.minLength(2)]),
    account: new FormGroup({
      email: new FormControl('', Validators.required),
      confirm: new FormControl('', Validators.required)
    })
  });
}
透過上述範例,我們可以看出,如果表單控制包含多種驗證規則,可以使用陣列宣告多種驗證規則。若只包含一種驗證規則,直接聲明就好。透過這種方式,我們就不需要在範本的輸入控制項中加入 required 屬性。接下來我們來新增表單驗證失敗時,不允許進行表單提交功能:

<form novalidate (ngSubmit)="onSubmit(user)" [formGroup]="user">
  ...
  <button type="submit" [disabled]="user.invalid">Sign up</button>
</form>
那麼問題來了,我們要如何取得表單控制項的驗證資訊?我們可以使用範本驅動表單中介紹的方式,具體如下:

<form novalidate [formGroup]="user">
  {{ user.controls.name?.errors | json }}
</form>
此外我們也可以使用FormGroup 物件提供的API,來取得表單控制項驗證的錯誤訊息:

<form novalidate [formGroup]="user">
  {{ user.get('name').errors | json }}
</form>
現在我們來看看完整的程式碼:

import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { User } from './signup.interface';

@Component({
  selector: 'signup-form',
  template: `
    <form novalidate (ngSubmit)="onSubmit(user)" [formGroup]="user">
      <label>
        <span>Full name</span>
        <input type="text" placeholder="Your full name" formControlName="name">
      </label>
      <p class="error" *ngIf="user.get(&#39;name&#39;).hasError(&#39;required&#39;) && 
            user.get(&#39;name&#39;).touched">
        Name is required
      </p>
      <p class="error" *ngIf="user.get(&#39;name&#39;).hasError(&#39;minlength&#39;) && 
            user.get(&#39;name&#39;).touched">
        Minimum of 2 characters
      </p>
      <p formGroupName="account">
        <label>
          <span>Email address</span>
          <input type="email" placeholder="Your email address" formControlName="email">
        </label>
        <p
          class="error"
          *ngIf="user.get(&#39;account&#39;).get(&#39;email&#39;).hasError(&#39;required&#39;) && 
             user.get(&#39;account&#39;).get(&#39;email&#39;).touched">
          Email is required
        </p>
        <label>
          <span>Confirm address</span>
          <input type="email" placeholder="Confirm your email address" 
             formControlName="confirm">
        </label>
        <p
          class="error"
          *ngIf="user.get(&#39;account&#39;).get(&#39;confirm&#39;).hasError(&#39;required&#39;) && 
             user.get(&#39;account&#39;).get(&#39;confirm&#39;).touched">
          Confirming email is required
        </p>
      </p>
      <button type="submit" [disabled]="user.invalid">Sign up</button>
    </form>
  `
})
export class SignupFormComponent implements OnInit {
  user: FormGroup;
  constructor() {}
  ngOnInit() {
    this.user = new FormGroup({
      name: new FormControl('', [Validators.required, Validators.minLength(2)]),
      account: new FormGroup({
        email: new FormControl('', Validators.required),
        confirm: new FormControl('', Validators.required)
      })
    });
  }
  onSubmit({ value, valid }: { value: User, valid: boolean }) {
    console.log(value, valid);
  }
}
功能是實作了,但創建FormGroup 物件的方式有點繁瑣,Angular 團隊也意識到這點,因此為我們提供FormBuilder ,來簡化上面的操作。

Simplifying with FormBuilder

首先我們需要從@angular/forms 匯入FormBuilder:

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

export class SignupFormComponent implements OnInit {
  user: FormGroup;
  constructor(private fb: FormBuilder) {}
  ...
}
然後我們使用FormBuilder 物件提供的group() 方法,來建立FormGroup 和FormControl 物件:

調整前的程式碼(未使用FormBuilder):

ngOnInit() {
  this.user = new FormGroup({
    name: new FormControl('', [Validators.required, Validators.minLength(2)]),
    account: new FormGroup({
      email: new FormControl('', Validators.required),
      confirm: new FormControl('', Validators.required)
    })
  });
}
調整後的程式碼(使用FormBuilder):

ngOnInit() {
  this.user = this.fb.group({
    name: ['', [Validators.required, Validators.minLength(2)]],
    account: this.fb.group({
      email: ['', Validators.required],
      confirm: ['', Validators.required]
    })
  });
}
對比調整前和調整後的程式碼,是不是覺得一下子方便了許多。此時更新完後完整的程式碼如下:

@Component({...})
export class SignupFormComponent implements OnInit {
  user: FormGroup;
  constructor(private fb: FormBuilder) {}
  ngOnInit() {
    this.user = this.fb.group({
      name: ['', [Validators.required, Validators.minLength(2)]],
      account: this.fb.group({
        email: ['', Validators.required],
        confirm: ['', Validators.required]
      })
    });
  }
  onSubmit({ value, valid }: { value: User, valid: boolean }) {
    console.log(value, valid);
  }
}
以上就是本文的全部內容,希望對大家的學習有所幫助,更多相關內容請關注PHP中文網!

相關推薦:

基於vue.js的dialog插件art-dialog-vue2.0的發佈內容

AngularJs與Angular 常用的指令寫法的區別

以上是關於Angular中響應式表單的介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn