序章
Angularは、フォームを操作する2つの方法を提供します。テンプレート駆動型フォームとリアクティブフォーム(モデル駆動型フォームとも呼ばれます)。 テンプレート駆動型フォームは、Angularでフォームを操作するためのデフォルトの方法です。 テンプレート駆動型フォームでは、テンプレートディレクティブを使用してフォームの内部表現を作成します。 リアクティブフォームを使用すると、コンポーネントクラスでフォームの独自の表現を作成できます。
注:リアクティブフォームはAngular2で導入されました。
反応型の利点のいくつかを次に示します。
- カスタムバリデーターの使用
- 検証を動的に変更する
- フォームフィールドを動的に追加する
この記事では、Angularアプリケーションの例にリアクティブフォームを適用する方法について説明します。
前提条件
この記事をフォローしたい場合は、次のものが必要になります。
- Node.jsはローカルにインストールされます。これは、Node.jsのインストール方法とローカル開発環境の作成に従って実行できます。
この投稿は、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>
このコードは、name、email、および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のときに値が指定された場合、その値がフィールドの初期値として使用されます。
FormGroupとFormControlの名前がテンプレートで使用されていたものと同じであることに注意してください。 また、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ブラウザーで開くことができます。 name、email、messageの値を入力し、送信を押すと、コンソールログに値が表示されます。
手順4—FormBuilderを使用するようにコンポーネントクラスを更新する
ngOnInitフォームの構成は、FormBuilderヘルパーを使用して書き直すことができます。 これにより、フォームグループとフォームコントロールのすべてのnewingを放棄できます。
コードエディタでapp.component.tsに戻り、FormControlを削除して、FormGroupをFormBuilderに置き換えます。
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);
}
}
このコードは、requiredをname、email、および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アプリケーションの例にリアクティブフォームを適用する方法について説明しました。 FormControl、FormGroup、FormBuilder、およびValidatorsを使用して、検証付きのサンプルフォームを作成しました。 その他の機能については、公式ドキュメントを参照してください。
Angularについて詳しく知りたい場合は、Angularトピックページで演習とプログラミングプロジェクトを確認してください。