スポンサーリンク

リアクティブフォームで複数組み合わせのバリデーションをする[Angular]

はじめに

リアクティブフォームのFormBuilderと、バリデーションを自作できるValidatorFnを使って、フォームの複数項目のデータを使ったバリデーションチェックを行います。

実装方法

実装内容

2つの入力項目をバリデーション対象として、片方のみの入力だった場合、不正とするようにバリデーションを作成していきます。

また、Angular 18で実装していきます。

バリデーション関数作成

2つのformControlとして、mainNoとsubNoを用意されているとして、
その値が、片方のみの入力だった場合に、不正とみなすように戻り値を返しています。

export function noValidator(): ValidatorFn {
    return (control: AbstractControl): ValidationErrors | null => {
      // 片方のみの入力を禁止する
      const mainNo = control.get('mainNo')?.value;
      const subNo = control.get("subNo")?.value;
      let isValid = false;
      if (
        (mainNo !== null && mainNo !== undefined && mainNo.trim() !== "") &&
        (subNo === null || subNo === undefined || subNo.trim() === "")
      ){
        isValid = true;
      } 
      else  if (
        (subNo !== null && subNo !== undefined && subNo.trim() !== "") &&
        (mainNo === null || mainNo === undefined || mainNo.trim() === "")
      ){
        isValid = true;
      }
      return isValid ? {isNoValidate: true} : null;
    };
}

コンポーネントの作成

以下のようにコンポーネントの作成します。

export class ExampleComponent {
  testForm!: FormGroup;
  isFormError: boolean = false;

  constructor(private fb: FormBuilder) {
    this.createForm();
  }

  createForm() {
    this.testForm = this.fb.group({
      mainNo: [''],
      subNo: ['']
    }, { validators: [noValidator()] });
  }

  onSubmit() {
    if (this.testForm.valid) {
      console.log(this.testForm.value);
    } else {
      console.log('Form is invalid');
      this.isFormError = true;
    }
  }  

}

注目してほしいのが以下の部分で、FormGroup全体に対して、自作したバリデーション関数を設定しているところです。
このように、全体に対してバリデーションを設定できるため、複数項目のバリデーションなどを設定できます。

  createForm() {
    this.testForm = this.fb.group({
      mainNo: [''],
      subNo: ['']
    }, { validators: [noValidator()] });
  }

テンプレートの作成

テンプレートを作成します。

<form [formGroup]="testForm" (ngSubmit)="onSubmit()">
  <div>
    <label for="mainNo">Main No.</label>
    <input id="mainNo" formControlName="mainNo" type="text">
  </div>

  <div>
    <label for="subNo">Sub No.</label>
    <input id="subNo" formControlName="subNo" type="text">
  </div>

  <button type="submit">送信</button>
  @if (isFormError) {
    <ul>
      @if (testForm.errors?.['isNoValidate']) {
        <li>Noは片方のみの入力はできません</li>
      }
    </ul>
  }
</form>

注目ポイントは以下で、バリデーション関数で設定していたキーを使って、不正かどうか判別できます。

    <ul>
      @if (testForm.errors?.['isNoValidate']) {
        <li>Noは片方のみの入力はできません</li>
      }
    </ul>

実行結果

以下のような形で、片方のみの入力を禁止できています。

まとめ

バリデーションの設定は、フォーム項目1つに対して設定している参考サイトが多いですが、全体に対しても設定できます。
その機能を使えば、複雑なバリデーションの設定をすることも可能になるかと思います。