【超解説】AngularフォームでformControlNameとformGroupNameを使いこなすテクニック
AngularでformControlName
とFormGroup
をネストする方法
ネストされたフォームグループの例
以下の例は、ユーザー情報と住所情報を含む、ネストされたフォームグループの例です。
<form [formGroup]="userForm">
<div formGroupName="userInfo">
<input type="text" formControlName="name" placeholder="名前">
<input type="email" formControlName="email" placeholder="メールアドレス">
</div>
<div formGroupName="address">
<input type="text" formControlName="street" placeholder="番地">
<input type="text" formControlName="city" placeholder="市区町村">
<input type="text" formControlName="postalCode" placeholder="郵便番号">
</div>
</form>
この例では、userForm
という名前の親フォームグループがあり、その中にuserInfo
とaddress
という名前の2つのネストされたフォームグループがあります。各フォームグループには、それぞれname
、email
、street
、city
、postalCode
という名前のフォームコントロールが含まれています。
formControlNameとformGroupNameの使い方
ネストされたフォームグループ内のフォームコントロールにアクセスするには、formControlName
ディレクティブとformGroupName
ディレクティブを組み合わせる必要があります。
formControlName
ディレクティブは、フォームコントロールの名前を指定します。formGroupName
ディレクティブは、ネストされたフォームグループの名前を指定します。
上記の例の場合、name
フォームコントロールにアクセスするには、次のように記述します。
<input type="text" formControlName="name" placeholder="名前">
この場合、formControlName
ディレクティブはname
という名前を指定していますが、単独ではどのフォームグループに属するフォームコントロールなのかを特定できません。そこで、formGroupName
ディレクティブを使用して、userInfo
という名前のネストされたフォームグループに属するフォームコントロールであることを明示する必要があります。
ネストされたフォームグループの値の取得と設定
ネストされたフォームグループの値を取得するには、FormGroup
インスタンスのget()
メソッドを使用します。設定するには、setValue()
メソッドを使用します。
// ユーザー情報の取得
const userInfo = userForm.get('userInfo').value;
console.log(userInfo.name); // "山田 太郎"
// 住所情報の更新
userForm.get('address').setValue({
street: '新横浜2丁目1-1',
city: '横浜市',
postalCode: '220-0001'
});
Angularでネストされたフォームグループを使用する場合は、formControlName
とformGroupName
ディレクティブを正しく組み合わせることで、フォームコントロールにアクセスしたり、値を取得・設定したりすることができます。
- ネストされたフォームグループは、さらに深くネストさせることができます。
- フォームコントロールとフォームグループには、さまざまなバリデーションルールを適用することができます。
- Reactive Formsは、複雑なフォームを扱うのに役立つ強力なツールです。
<!DOCTYPE html>
<html>
<head>
<title>Nested Form Groups Example</title>
<script src="https://unpkg.com/@angular/core@latest"></script>
<script src="https://unpkg.com/@angular/forms@latest"></script>
<script src="app.component.ts"></script>
</head>
<body>
<app-root></app-root>
</body>
</html>
import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
@Component({
selector: 'app-root',
template: `
<form [formGroup]="userForm">
<div formGroupName="userInfo">
<input type="text" formControlName="name" placeholder="名前">
<input type="email" formControlName="email" placeholder="メールアドレス">
</div>
<div formGroupName="address">
<input type="text" formControlName="street" placeholder="番地">
<input type="text" formControlName="city" placeholder="市区町村">
<input type="text" formControlName="postalCode" placeholder="郵便番号">
</div>
<button type="button" (click)="onSubmit()">送信</button>
</form>
`
})
export class AppComponent {
userForm = new FormGroup({
userInfo: new FormGroup({
name: new FormControl('', [Validators.required]),
email: new FormControl('', [Validators.required, Validators.email]),
}),
address: new FormGroup({
street: new FormControl('', [Validators.required]),
city: new FormControl('', [Validators.required]),
postalCode: new FormControl('', [Validators.required, Validators.pattern(/^\d{3}-\d{4}$/)]),
}),
});
onSubmit() {
console.log(this.userForm.value);
}
}
このコードでは、以下の処理が行われています。
FormGroup
インスタンスを2つ作成します。1つはユーザー情報用、もう1つは住所情報用です。- 各フォームグループには、それぞれ
FormControl
インスタンスを複数作成します。各フォームコントロールには、バリデーションルールを設定します。 - 親フォームグループを
userForm
という変数に格納します。 - テンプレートで、
formGroup
ディレクティブを使用して親フォームグループにバインドします。 onSubmit()
メソッドで、フォーム送信時にフォームの値をコンソールに出力します。
注意事項
FormBuilderを使用する
FormBuilder
クラスは、フォームグループとフォームコントロールを簡単に作成するための便利なツールです。ネストされたフォームグループを作成する場合にも、FormBuilder
を使用することができます。
import { FormBuilder } from '@angular/forms';
const userForm = new FormBuilder().group({
userInfo: new FormBuilder().group({
name: ['', Validators.required],
email: ['', [Validators.required, Validators.email]],
}),
address: new FormBuilder().group({
street: ['', Validators.required],
city: ['', Validators.required],
postalCode: ['', [Validators.required, Validators.pattern(/^\d{3}-\d{4}$/)]],
}),
});
テンプレート駆動フォームを使用する
Angularには、Reactive Forms以外にもテンプレート駆動フォームというフォーム処理方法があります。テンプレート駆動フォームは、フォームの値をテンプレート内で直接操作できるという利点があります。
ネストされたフォームグループをテンプレート駆動フォームで扱う場合、ngModel
ディレクティブとformGroup
ディレクティブを組み合わせる必要があります。
<form [formGroup]="userForm">
<div formGroupName="userInfo">
<input type="text" [(ngModel)]="userForm.get('userInfo.name').value" placeholder="名前">
<input type="email" [(ngModel)]="userForm.get('userInfo.email').value" placeholder="メールアドレス">
</div>
<div formGroupName="address">
<input type="text" [(ngModel)]="userForm.get('address.street').value" placeholder="番地">
<input type="text" [(ngModel)]="userForm.get('address.city').value" placeholder="市区町村">
<input type="text" [(ngModel)]="userForm.get('address.postalCode').value" placeholder="郵便番号">
</div>
<button type="button" (click)="onSubmit()">送信</button>
</form>
フォームコンポーネントを使用する
フォームコンポーネントは、再利用可能なフォーム部品を作成するための便利な方法です。ネストされたフォームグループをフォームコンポーネントとして作成することもできます。
フォームコンポーネントを作成するには、以下の手順が必要です。
- フォームコンポーネント用のクラスを作成します。
- クラス内に、フォームグループとテンプレートを定義します。
- フォームコンポーネントを
@Component
デコレータでデコレートします。 - テンプレートで、フォームコンポーネントを使用します。
<div formGroupName="userInfo">
<input type="text" formControlName="name" placeholder="名前">
<input type="email" formControlName="email" placeholder="メールアドレス">
</div>
<user-info-form [formGroup]="userForm"></user-info-form>
このコードは、ユーザー情報用のフォームコンポーネントを作成し、親コンポーネントで使用しています。フォームコンポーネントを使用すると、コードをよりモジュール化し、再利用することができます。
どの方法を選択するべきか?
どの方法を選択するかは、アプリケーションの要件によって異なります。
- シンプルなフォームを作成する場合は、
formControlName
とformGroupName
ディレクティブを使用するだけで十分です。 - より複雑なフォームを作成する場合は、
FormBuilder
やテンプレート駆動フォームを使用すると、コードがより簡潔で読みやすくなります。 - 再利用可能なフォーム部品を作成する場合は、フォームコンポーネントを使用します。
forms angular angular-reactive-forms