今回は、独自エラーチェック(カスタムバリデーション)を作成します。
プログラムは、以前の記事で使用した「アカウント登録機能」を使用したいと思いますので、下記の記事も参照ください。
参照1:【Angular】コンポーネントの設計(画面ごとの設計)について。
参照2:【Angular】エラーメッセージの管理について考える。
(1)登録画面の実装を確認
まずは、現在の登録画面のコンポーネントを見てみます。コード量が多いので、全体はこちら(register.component.ts)で確認ください
今回カスタムバリデーションを追加するのは、こちらの携帯番号(mobilePhoneNumber)部分です。
mobilePhoneNumberMaxLength = 11;
nameMaxLength = 20;
// (中略)
formRegister: FormGroup = this.formBuilder.group({
mobilePhoneNumber: ['',[Validators.required,Validators.maxLength(this.mobilePhoneNumberMaxLength)]],
name: ['', [Validators.maxLength(this.nameMaxLength)]],
});
しかし、これだけだと、「18011112222」のような「0」始まりではない番号はエラーになりません。
このチェックを独自で作成しようと思いますが、
その前に、一応テンプレート側の記載も見ておこうと思います。
こちらもコード量が多いので、全体はこちら(register.component.html)で確認ください
下記に、今回関係する部分だけ記載しておきます。
<div>
<label>携帯電話番号<span>必須</span></label>
<input formControlName="mobilePhoneNumber" type="tel" inputmode="numeric" class="form-control" placeholder="携帯電話番号を入力"
[ngClass]="{'alert-danger' : v.mobilePhoneNumberInvalid}" autofocus>
<ng-container *ngIf="v.mobilePhoneNumberInvalid">
<p *ngIf="v.mobilePhoneNumberHasErrorRequired" class="error-message">{{ message('msg_error_field_required', '携帯電話番号') }}</p>
<p *ngIf="v.mobilePhoneNumberHasErrorMaxLength" class="error-message">{{ message('msg_error_field_max', '携帯電話番号', mobilePhoneNumberMaxLength) }}</p>
</ng-container>
</div>
(2)カスタムバリデーションを作成する
弊社のプロジェクトでは、「app」配下に「shared」と言うディレクトリを作り、その中にプロジェクトで共通的に使うものを配置しています。今回のカスタムバリデーションも、共通的に使われるものなので、、以下のように作成します。
src/
└ app/
└ shared/
└ validator/
└ custom-validators.ts
では、携帯電話番号のチェックを実装しようと思います。
[custom-validators.ts]
import { FormControl } from '@angular/forms';
export class CustomValidators {
/**
* 携帯電話番号かどうか判定
* @param control Formのコントロール
*/
static mobilePhoneNumberValidator(control: FormControl) {
const dateObj = control.value;
// 当メソッドでは、電話番号は空文字で登録することも許可する
if (dateObj === '') {
return null;
}
const regexp = new RegExp('^(0{1}\\d{10})');
if (
typeof dateObj === 'undefined' ||
dateObj === null ||
!regexp.test(dateObj)
) {
return { mobilePhoneNumberFormat: true };
}
return null;
}
}
「当メソッドでは、電話番号は空文字で登録することも許可する」と言うコメントの部分が特殊なのですが、例えば、「任意の項目」でこのバリデーションを使いたくなった場合、そのまま使うと「未入力」でもエラーになってしまうので、未入力はエラーとしないようにしています。
どっちにしても、必須かどうかは、通常のバリデーションで行なっているので、そちらに任せる、と言う感じです。
それと、「携帯電話番号かどうか」はかなり適当に記載していますので、ご了承ください(今回は、その説明が本質では無いので)
ちょっと分かり難い(勘違いしやすい)のですが、「エラーになるパターンは『true』を返却し、エラーとしない場合『null』を返却しています」
(3)作成したカスタムバリデーションを使う
では、作成したカスタムバリデーションを実際に使ってみます。「register.component.ts」に実装していきますが、まずは先ほどのカスタムバリデーションをimportします。
import { CustomValidators } from '@app/shared/validator/custom-validators';
importしたカスタムバリデーションは、通常のバリデーションと同じ流れで定義します。
formRegister: FormGroup = this.formBuilder.group({
mobilePhoneNumber: [
'',
[
Validators.required, // ←通常のバリデーション
Validators.maxLength(this.mobilePhoneNumberMaxLength), // ←通常のバリデーション
CustomValidators.mobilePhoneNumberValidator, // ←カスタムバリデーション
],
],
name: ['', [Validators.maxLength(this.nameMaxLength)]],
});
とても簡単ですね、次は、別ファイルにしている「register.validator.ts」にも追記します。
こちらは、全文そのまま記載しようと思います。
[register.component.html]
import { Injectable } from '@angular/core';
import { FormGroup } from '@angular/forms';
@Injectable()
export class RegisterValidator {
private form: FormGroup;
constructor() {}
set formGroup(form: FormGroup) {
this.form = form;
}
get mobilePhoneNumberInvalid() {
return (
this.form.controls['mobilePhoneNumber'].invalid &&
(this.form.controls['mobilePhoneNumber'].dirty ||
this.form.controls['mobilePhoneNumber'].touched)
);
}
get mobilePhoneNumberHasErrorRequired() {
return this.form.controls['mobilePhoneNumber'].hasError('required');
}
get mobilePhoneNumberHasErrorMaxLength() {
return (
!this.form.controls['mobilePhoneNumber'].hasError('required') &&
this.form.controls['mobilePhoneNumber'].hasError('maxlength')
);
}
get mobilePhoneNumberHasErrorFormat() {
return (
!this.form.controls['mobilePhoneNumber'].hasError('required') &&
this.form.controls['mobilePhoneNumber'].hasError(
'mobilePhoneNumberFormat',
)
);
}
get nameInvalid() {
return (
this.form.controls['name'].invalid &&
(this.form.controls['name'].dirty || this.form.controls['name'].touched)
);
}
get nameHasErrorMaxLength() {
return this.form.controls['name'].hasError('maxlength');
}
}
追記した部分は以下の通りです。
get mobilePhoneNumberHasErrorFormat() {
return (
!this.form.controls['mobilePhoneNumber'].hasError('required') &&
this.form.controls['mobilePhoneNumber'].hasError(
'mobilePhoneNumberFormat',
)
);
}
この「mobilePhoneNumberHasErrorFormat」は、テンプレート側で使うことになります。では、そのテンプレート側も変更しようと思います。
<div>
<label>携帯電話番号<span>必須</span></label>
<input formControlName="mobilePhoneNumber" type="tel" inputmode="numeric" class="form-control" placeholder="携帯電話番号を入力"
[ngClass]="{'alert-danger' : v.mobilePhoneNumberInvalid}" autofocus>
<ng-container *ngIf="v.mobilePhoneNumberInvalid">
<p *ngIf="v.mobilePhoneNumberHasErrorRequired" class="error-message">{{ message('msg_error_field_required', '携帯電話番号') }}</p>
<p *ngIf="v.mobilePhoneNumberHasErrorMaxLength" class="error-message">{{ message('msg_error_field_max', '携帯電話番号', mobilePhoneNumberMaxLength) }}</p>
<p *ngIf="v.mobilePhoneNumberHasErrorFormat" class="error-message">{{ message('msg_error_cellphone_number') }}</p>
</ng-container>
</div>
下記が追加した部分です。今回、新たにエラーメッセージも追加しています。
(エラーメッセージの管理については、「【Angular】エラーメッセージの管理について考える。」を参照ください)
<p *ngIf="v.mobilePhoneNumberHasErrorFormat" class="error-message">{{ message('msg_error_cellphone_number') }}</p>
これで、独自エラーチェック(カスタムバリデーション)を実装できました。
ある程度規模の大きいプロジェクトになると、結構な数のカスタムバリデーションを作る事になるかと思いますので、参考にして頂ければ幸いです。
Angular

0 件のコメント:
コメントを投稿