フォームコントロール・フォームグループはどうやれば実装できる?
Angularには、FormControlとFormGroupを活用して簡単にフォームを作成できる機能があります。
この記事では、以下のことを解説します。
- フォームコントロール
- フォームグループ
- バリデーション
- フォームの値を取得する
※AngularMaterialを導入済みなので、フォームもMaterialデザインのものを使用します。AngularMaterialの導入
※Anular14
休日で空いた時間の暇つぶしを探せるアプリを公開しています。
フォームを追加する
今回作成するフォームは、名前・住所・電話番号・メールアドレス・パスワード・パスワード(確認用)のフォームです。
以下のように、フォームを作成するのに必要なFormControlやFormGroupなどをまずはimportしてください。
そして、constructorの前で、フォームの変数を書きます。そして、ngOnInitでFormControlをnewします。
import { Component, OnInit } from '@angular/core';
import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-user-register',
templateUrl: './user-register.component.html',
styleUrls: ['./user-register.component.css']
})
export class UserRegisterComponent implements OnInit {
public name: FormControl;
public address: FormControl;
public phone: FormControl;
public email: FormControl;
public password: FormControl;
public passwordConfirm: FormControl;
constructor() {}
ngOnInit(): void {
this.name = new FormControl('');
this.address = new FormControl('');
this.phone = new FormControl('');
this.email = new FormControl('');
this.password = new FormControl('');
this.passwordConfirm = new FormControl('');
}
}
new FormControlでフォームを追加したら、HTML側では以下のように[formControl]=”フォーム名”でフォームをセットできます。[formControl]ではなく、formControlNameでも代用できます。
<form class="form-field">
<!-- 名前のフォーム -->
<mat-form-field appearance="fill">
<mat-label>名前</mat-label>
<input matInput placeholder="名前を入力してください" [formControl]="name">
</mat-form-field>
<!-- 住所のフォーム -->
<mat-form-field appearance="fill">
<mat-label>住所</mat-label>
<input matInput placeholder="住所を入力してください" [formControl]="address">
</mat-form-field>
<!-- 電話番号のフォーム -->
<mat-form-field appearance="fill">
<mat-label>電話番号</mat-label>
<input matInput placeholder="電話番号を入力してください" [formControl]="phone">
</mat-form-field>
<!-- メールアドレスのフォーム -->
<mat-form-field appearance="fill">
<mat-label>メールアドレス</mat-label>
<input matInput placeholder="メールアドレスを入力してください" [formControl]="email">
</mat-form-field>
<!-- パスワードのフォーム -->
<mat-form-field appearance="fill">
<mat-label>パスワード</mat-label>
<input matInput placeholder="パスワードを入力してください" [formControl]="password">
</mat-form-field>
<!-- パスワード(確認用)のフォーム -->
<mat-form-field appearance="fill">
<mat-label>パスワード(確認用)</mat-label>
<input matInput placeholder="パスワード(確認用)を入力してください" [formControl]="passwordConfirm">
</mat-form-field>
<button class="form-button" mat-raised-button color="primary" [disabled]="">登録する</button>
</form>
mat-form-fieldにappearance=”fill”をつけなければ、以下のようなフォームになります。
.form-field {
width: 100%;
padding: 50px;
}
mat-form-field {
width: 80%;
padding-bottom: 1rem;
}
.form-button {
display: block;
width: 80%;
}
mat-buttonが反映されない場合は、app.module.tsでMatButtonModuleをimportしているか確認しましょう。
バリデーションを設定する
簡単に書くフォームに必須バリデーションぐらいかけておきましょう。
Validatorsをimportしていることを確認してください。
そしたら、あとはnew FormControl(”)としたところにValidators.requiredを加え、HTMLにはmat-errorを追加します。
import { Component, OnInit } from '@angular/core';
import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-user-register',
templateUrl: './user-register.component.html',
styleUrls: ['./user-register.component.css']
})
export class UserRegisterComponent implements OnInit {
public name: FormControl;
public address: FormControl;
public phone: FormControl;
public email: FormControl;
public password: FormControl;
public passwordConfirm: FormControl;
constructor() {}
ngOnInit(): void {
this.name = new FormControl('', Validators.required);
this.address = new FormControl('', Validators.required);
this.phone = new FormControl('', Validators.required);
this.email = new FormControl('', Validators.required);
this.password = new FormControl('', Validators.required);
this.passwordConfirm = new FormControl('', Validators.required);
}
}
<form class="form-field">
<!-- 名前のフォーム -->
<mat-form-field appearance="fill">
<mat-label>名前</mat-label>
<input matInput placeholder="名前を入力してください" [formControl]="name">
<mat-error *ngIf="name.errors?.['required']">必須です。</mat-error>
</mat-form-field>
<!-- 住所のフォーム -->
<mat-form-field appearance="fill">
<mat-label>住所</mat-label>
<input matInput placeholder="住所を入力してください" [formControl]="name">
<mat-error *ngIf="name.errors?.['required']">必須です。</mat-error>
</mat-form-field>
<!-- 電話番号のフォーム -->
<mat-form-field appearance="fill">
<mat-label>電話番号</mat-label>
<input matInput placeholder="電話番号を入力してください" [formControl]="name">
<mat-error *ngIf="name.errors?.['required']">必須です。</mat-error>
</mat-form-field>
<!-- メールアドレスのフォーム -->
<mat-form-field appearance="fill">
<mat-label>メールアドレス</mat-label>
<input matInput placeholder="メールアドレスを入力してください" [formControl]="name">
<mat-error *ngIf="name.errors?.['required']">必須です。</mat-error>
</mat-form-field>
<!-- パスワードのフォーム -->
<mat-form-field appearance="fill">
<mat-label>パスワード</mat-label>
<input matInput placeholder="パスワードを入力してください" [formControl]="name">
<mat-error *ngIf="name.errors?.['required']">必須です。</mat-error>
</mat-form-field>
<!-- パスワード(確認用)のフォーム -->
<mat-form-field appearance="fill">
<mat-label>パスワード(確認用)</mat-label>
<input matInput placeholder="パスワード(確認用)を入力してください" [formControl]="name">
<mat-error *ngIf="name.errors?.['required']">必須です。</mat-error>
</mat-form-field>
<button class="form-button" mat-raised-button color="primary" [disabled]="">登録する</button>
</form>
登録するボタンを押したときに、フォームに何も入力されていなければ、必須です。とバリデーションエラーを起こします。
ただ、このように複数のフォームがある場合は、フォームをグループ化するのが良いです。
なぜならFormControlは、単一のフォームを制御しますが、フォーム全体である名前〜パスワード(確認用)までは面倒見ません。
グループ化することで、フォーム全体を管理できます。
グループ化したフォームで、名前のフォームでバリデーションエラーが起きていた場合にボタンを非活性にすることもできます。バリデーションエラーが解消されたら、動的に活性化されます。便利ですね。
フォームをグループ化する
フォームをグループ化します。
FormControlみたいに、new FormGroupし、フォーム名: フォームコントロールのようにセットすればOKです。
import { Component, OnInit } from '@angular/core';
import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-user-register',
templateUrl: './user-register.component.html',
styleUrls: ['./user-register.component.css']
})
export class UserRegisterComponent implements OnInit {
public registerForm: FormGroup;
public name: FormControl;
public address: FormControl;
public phone: FormControl;
public email: FormControl;
public password: FormControl;
public passwordConfirm: FormControl;
constructor() {}
ngOnInit(): void {
this.name = new FormControl('', Validators.required);
this.address = new FormControl('', Validators.required);
this.phone = new FormControl('', Validators.required);
this.email = new FormControl('', Validators.required);
this.password = new FormControl('', Validators.required);
this.passwordConfirm = new FormControl('', Validators.required);
this.registerForm = new FormGroup({
name: this.name,
address: this.address,
phone: this.phone,
email: this.email,
password: this.password,
passwordConfirm: this.passwordConfirm,
});
}
}
HTML側では[formGroup]=”フォームグループ名”を追加します。
そして、ボタンには[disabled]を追加します。=trueの場合はボタン活性化、falseの場合は非活性
フォームグループでバリデーションエラーが発生しているか判定するには、フォームグループ名.invalidで実現できます。
<form class="form-field" [formGroup]="registerForm">
<!-- 名前のフォーム -->
<mat-form-field appearance="fill">
<mat-label>名前</mat-label>
<input matInput placeholder="名前を入力してください" [formControl]="name">
<mat-error *ngIf="name.errors?.['required']">必須です。</mat-error>
</mat-form-field>
<!-- 住所のフォーム -->
<mat-form-field appearance="fill">
<mat-label>住所</mat-label>
<input matInput placeholder="住所を入力してください" [formControl]="address">
<mat-error *ngIf="address.errors?.['required']">必須です。</mat-error>
</mat-form-field>
<!-- 電話番号のフォーム -->
<mat-form-field appearance="fill">
<mat-label>電話番号</mat-label>
<input matInput placeholder="電話番号を入力してください" [formControl]="phone">
<mat-error *ngIf="phone.errors?.['required']">必須です。</mat-error>
</mat-form-field>
<!-- メールアドレスのフォーム -->
<mat-form-field appearance="fill">
<mat-label>メールアドレス</mat-label>
<input matInput placeholder="メールアドレスを入力してください" [formControl]="email">
<mat-error *ngIf="email.errors?.['required']">必須です。</mat-error>
</mat-form-field>
<!-- パスワードのフォーム -->
<mat-form-field appearance="fill">
<mat-label>パスワード</mat-label>
<input matInput placeholder="パスワードを入力してください" [formControl]="password">
<mat-error *ngIf="password.errors?.['required']">必須です。</mat-error>
</mat-form-field>
<!-- パスワード(確認用)のフォーム -->
<mat-form-field appearance="fill">
<mat-label>パスワード(確認用)</mat-label>
<input matInput placeholder="パスワード(確認用)を入力してください" [formControl]="passwordConfirm">
<mat-error *ngIf="passwordConfirm.errors?.['required']">必須です。</mat-error>
</mat-form-field>
<button class="form-button" mat-raised-button color="primary" [disabled]="registerForm.invalid">登録する</button>
</form>
バリデーションには、各フォームに必須のみ付けているので、初期画面遷移時は、必須チェックに引っかかって登録するボタンは非活性になります。
どれかでバリデーションエラーあっても登録するボタンは非活性
バリデーションエラーがなくなったら、登録するボタンは活性化
登録するボタンの送信イベント
登録するボタンを押したときに送信するイベントは簡単でHTML側でngSubmitを追加するだけです。
import { Component, OnInit } from '@angular/core';
import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-user-register',
templateUrl: './user-register.component.html',
styleUrls: ['./user-register.component.css']
})
export class UserRegisterComponent implements OnInit {
public registerForm: FormGroup;
public name: FormControl;
public address: FormControl;
public phone: FormControl;
public email: FormControl;
public password: FormControl;
public passwordConfirm: FormControl;
constructor() {}
ngOnInit(): void {
this.name = new FormControl('', Validators.required);
this.address = new FormControl('', Validators.required);
this.phone = new FormControl('', Validators.required);
this.email = new FormControl('', Validators.required);
this.password = new FormControl('', Validators.required);
this.passwordConfirm = new FormControl('', Validators.required);
this.registerForm = new FormGroup({
name: this.name,
address: this.address,
phone: this.phone,
email: this.email,
password: this.password,
passwordConfirm: this.passwordConfirm,
});
}
onSubmit() {
console.log('クリック');
}
}
以下のようにngSubmitを追加することで、登録するボタンを押したときにイベントが発生します。
追加:(ngSubmit)=”onSubmit()”
<form class="form-field" [formGroup]="registerForm" (ngSubmit)="onSubmit()">
<!-- 名前のフォーム -->
<mat-form-field appearance="fill">
<mat-label>名前</mat-label>
<input matInput placeholder="名前を入力してください" [formControl]="name">
<mat-error *ngIf="name.errors?.['required']">必須です。</mat-error>
</mat-form-field>
<!-- 住所のフォーム -->
<mat-form-field appearance="fill">
<mat-label>住所</mat-label>
<input matInput placeholder="住所を入力してください" [formControl]="address">
<mat-error *ngIf="address.errors?.['required']">必須です。</mat-error>
</mat-form-field>
<!-- 電話番号のフォーム -->
<mat-form-field appearance="fill">
<mat-label>電話番号</mat-label>
<input matInput placeholder="電話番号を入力してください" [formControl]="phone">
<mat-error *ngIf="phone.errors?.['required']">必須です。</mat-error>
</mat-form-field>
<!-- メールアドレスのフォーム -->
<mat-form-field appearance="fill">
<mat-label>メールアドレス</mat-label>
<input matInput placeholder="メールアドレスを入力してください" [formControl]="email">
<mat-error *ngIf="email.errors?.['required']">必須です。</mat-error>
</mat-form-field>
<!-- パスワードのフォーム -->
<mat-form-field appearance="fill">
<mat-label>パスワード</mat-label>
<input matInput placeholder="パスワードを入力してください" [formControl]="password">
<mat-error *ngIf="password.errors?.['required']">必須です。</mat-error>
</mat-form-field>
<!-- パスワード(確認用)のフォーム -->
<mat-form-field appearance="fill">
<mat-label>パスワード(確認用)</mat-label>
<input matInput placeholder="パスワード(確認用)を入力してください" [formControl]="passwordConfirm">
<mat-error *ngIf="passwordConfirm.errors?.['required']">必須です。</mat-error>
</mat-form-field>
<button class="form-button" mat-raised-button color="primary" [disabled]="registerForm.invalid">登録する</button>
</form>
活性化されている登録するボタンを押したら、コンソールにクリックと表示されます。
フォームの値を取得する
フォームの値を取得するには、フォームコントロール.valueで取得できます。
onSubmit() {
console.log('クリック');
// 名前のフォームの値を取得する
const name = this.name.value;
console.log(name);
}
休日で空いた時間の暇つぶしを探せるアプリを公開しています。
コメント