Angularでリアクティブフォームを使用する方法

提供:Dev Guides
移動先:案内検索

序章

Angularは、フォームを操作する2つの方法を提供します。テンプレート駆動型フォームリアクティブフォームモデル駆動型フォームとも呼ばれます)。 テンプレート駆動型フォームは、Angularでフォームを操作するためのデフォルトの方法です。 テンプレート駆動型フォームでは、テンプレートディレクティブを使用してフォームの内部表現を作成します。 リアクティブフォームを使用すると、コンポーネントクラスでフォームの独自の表現を作成できます。

注:リアクティブフォームはAngular2で導入されました。


反応型の利点のいくつかを次に示します。

この記事では、Angularアプリケーションの例にリアクティブフォームを適用する方法について説明します。

前提条件

この記事をフォローしたい場合は、次のものが必要になります。

この投稿は、Angularの基本的な知識があることを前提としています。

この投稿では、@angular/cliによって生成された新しいAngularプロジェクトからビルドしていることも前提としています。 Angular CLIを使い始めた場合は、この投稿を参照できます。

このチュートリアルは、ノードv15.1.0、npm v6.14.8、@angular/core v11.0.0、および@angular/formsv11.0.0で検証されました。

ステップ1—プロジェクトの設定

このチュートリアルでは、@angular/cliで生成されたデフォルトのAngularプロジェクトからビルドします。

npx @angular/cli new angular-reactive-forms-example --style=css --routing=false --skip-tests

これにより、スタイルが「CSS」(「Sass」、「Less」、「Stylus」ではなく)に設定され、ルーティングがなく、テストがスキップされる新しいAngularプロジェクトが構成されます。

新しく作成されたプロジェクトディレクトリに移動します。

cd angular-reactive-forms-example

リアクティブフォームを操作するには、FormsModuleの代わりにReactiveFormsModuleを使用します。

コードエディタでapp.module.tsを開き、ReactiveFormsModuleを追加します。

src / app / app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    ReactiveFormsModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

この時点で、ReactiveFormsModuleを使用した新しいAngularプロジェクトが作成されているはずです。

ステップ2—コンポーネントテンプレートにフォームを追加する

リアクティブフォームでは、ロジックは完全にコンポーネントクラスで宣言されます。

コードエディタでapp.component.htmlを開き、次のコード行を追加します。

src / app / app.component.html

<form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm)">
  <div>
    <label>
      Name:
      <input formControlName="name" placeholder="Your name">
    </label>
  </div>
  <div>
    <label>
      Email:
      <input formControlName="email" placeholder="Your email">
    </label>
  </div>
  <div>
    <label>
      Message:
      <input formControlName="message" placeholder="Your message">
    </label>
  </div>
  <button type="submit">Send</button>
</form>

このコードは、nameemail、およびmessageの3つのフィールドを持つフォームを作成します。 "Send"というラベルの付いた"submit"ボタンもあります。 フォームを送信すると、メソッドonSubmit(myForm)が呼び出されます。

注: Angular 2.xを使用している場合は、novalidateディレクティブを開始formタグとともに追加する必要があります。これは、AngularがHTML5の検証をオーバーライドするためです。 Angular 4+では、novalidateが舞台裏で自動的に追加されます。


それを分解しましょう:

  • formGroup:フォームはコンポーネントクラスでFormGroupとして扱われるため、formGroupディレクティブを使用すると、フォームグループに名前を付けることができます。
  • ngSubmit:これはフォームの送信時にトリガーされるイベントです。
  • formControlName:各フォームフィールドには、コンポーネントクラスで使用される名前となる値を持つformControlNameディレクティブが必要です。

この時点で、フォームを使用するコンポーネントテンプレートを備えた新しいAngularプロジェクトが作成されているはずです。

ステップ3—コンポーネントクラスを構築する

次に、コンポーネントクラスで、FormGroup内のFormGroupと個々のFormControlを定義します。

newing a FormControlのときに値が指定された場合、その値がフィールドの初期値として使用されます。

FormGroupFormControlの名前がテンプレートで使用されていたものと同じであることに注意してください。 また、ngOnInitライフサイクルフックFormGroupを初期化する方法にも注意してください。

src / app / app.component.ts

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  myForm: FormGroup;

  ngOnInit() {
    this.myForm = new FormGroup({
      name: new FormControl('Sammy'),
      email: new FormControl(''),
      message: new FormControl('')
    });
  }

  onSubmit(form: FormGroup) {
    console.log('Valid?', form.valid); // true or false
    console.log('Name', form.value.name);
    console.log('Email', form.value.email);
    console.log('Message', form.value.message);
  }
}

このチュートリアルでは、onSubmitメソッドは、送信されたフォームの値を外部のサービスやサーバーに実際に伝達しません。 これは、フォームの有効性とFormControl値にアクセスする方法を示すのに役立ちます。

この時点で、アプリケーションをコンパイルしてWebブラウザーで開くことができます。 nameemailmessageの値を入力し、送信を押すと、コンソールログに値が表示されます。

手順4—FormBuilderを使用するようにコンポーネントクラスを更新する

ngOnInitフォームの構成は、FormBuilderヘルパーを使用して書き直すことができます。 これにより、フォームグループとフォームコントロールのすべてのnewingを放棄できます。

コードエディタでapp.component.tsに戻り、FormControlを削除して、FormGroupFormBuilderに置き換えます。

src / app / app.component.ts

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  myForm: FormGroup;

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.myForm = this.fb.group({
      name: 'Sammy',
      email: '',
      message: ''
    });
  }

  onSubmit(form: FormGroup) {
    console.log('Valid?', form.valid); // true or false
    console.log('Name', form.value.name);
    console.log('Email', form.value.email);
    console.log('Message', form.value.message);
  }
}

FormBuilderを含むこのコードは、FormGroupを作成するためのボイラープレートコードの量を減らします。

手順5—Validatorsを使用するようにコンポーネントクラスを更新する

Validatorsクラスをインポートに追加し、単純な文字列値の代わりに配列を使用してフォームコントロールを宣言します。

配列の最初の値は初期フォーム値であり、2番目の値はバリデーターが使用するためのものです。 複数のバリデーターを配列にラップすることで、同じフォームコントロールで使用できることに注目してください。

コードエディタでapp.component.tsを再確認し、Validatorsを追加します。

src / app / app.component.ts

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  myForm: FormGroup;

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.myForm = this.fb.group({
      name: ['Sammy', Validators.required],
      email: ['', [Validators.required, Validators.email]],
      message: ['', [Validators.required, Validators.minLength(15)]],
    });
  }

  onSubmit(form: FormGroup) {
    console.log('Valid?', form.valid); // true or false
    console.log('Name', form.value.name);
    console.log('Email', form.value.email);
    console.log('Message', form.value.message);
  }
}

このコードは、requirednameemail、およびmessageフィールドに追加します。 また、email値が有効な電子メールアドレスの形式を使用することも保証します。 また、message値が少なくとも15文字の長さであることを確認します。

これらのフォーム要件のいずれかが合格しない場合、validの値はfalseになります。 これらのフォーム要件がすべて合格している場合、validの値はtrueになります。

ステップ6—テンプレートのフォーム値と有効性へのアクセス

テンプレートでは、各FormControlの値と有効性、およびフォームグループ全体の値と有効性にアクセスできます。

app.component.htmlに再度アクセスし、*ngIfを使用して、フォームの値が無効な場合にユーザーにフィードバックメッセージを表示します。

src / app / app.component.html

<form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm)">
  <div>
    <label>
      Name:
      <input formControlName="name" placeholder="Your name">
    </label>
    <div *ngIf="myForm.get('name').invalid && (myForm.get('name').dirty || myForm.get('name').touched)">
      Please provide a name.
    </div>
  </div>
  <div>
    <label>
      Email:
      <input formControlName="email" placeholder="Your email">
    </label>
    <div *ngIf="myForm.get('email').invalid && (myForm.get('email').dirty || myForm.get('email').touched)">
      Please provide a valid email address.
    </div>
  </div>
  <div>
    <label>
      Message:
      <input formControlName="message" placeholder="Your message">
    </label>
    <div *ngIf="myForm.get('message').invalid && (myForm.get('message').dirty || myForm.get('message').touched)">
      Messages must be at least 15 characters long.
    </div>
  </div>
  <button type="submit" [disabled]="myForm.invalid">Send</button>
</form>

このコードは、ユーザーがフィールド(dirtyまたはtouched)を操作したかどうかを確認します。 次に、値が検証要件に合格していない場合は、エラーメッセージが表示されます。 送信ボタンも、フォーム値に関するすべての問題が解決されるまで無効になります。

フォーム制御値を取得する方法は複数あります。 この例では、myForm.controls.nameと同等のmyForm.get('name')を使用しています。 .hasError('required')または.errors.requiredでエラー情報を取得することができます。

結論

この記事では、Angularアプリケーションの例にリアクティブフォームを適用する方法について説明しました。 FormControlFormGroupFormBuilder、およびValidatorsを使用して、検証付きのサンプルフォームを作成しました。 その他の機能については、公式ドキュメントを参照してください。

Angularについて詳しく知りたい場合は、Angularトピックページで演習とプログラミングプロジェクトを確認してください。