インフラジスティックス・ジャパン株式会社Blog

インフラジスティックス・ジャパン株式会社のチームメンバーが技術トレンド、製品Tips、サポート情報からライセンス、日々の業務から感じることなど、さまざまなトピックについてお伝えするBlogです。

Angular Reactive Forms の valueChanges メソッドで条件付き検証を行う方法

このブログ投稿では、Angular Reactive Forms の値の変更検出を使用し、それに基づいて条件付き検証を有効にする方法を学習します。

はじめての Angular Reactive Form を作成する方法はこちら(英語ブログ)を参照してください。

この記事はインフラジスティックス本社により作成された英文記事の機械翻訳により生成されました。
原文は以下よりご確認いただけます。
[Dhananjay Kumar](https://www.infragistics.com/community/blogs/p/contributor?un=6D51D762E2AB55B5A630B24A2652C50B78141C00) 2018.3.15  [How to do Conditional Validation on valueChanges method in Angular Reactive Forms](https://www.infragistics.com/community/blogs/p/contributor?un=6D51D762E2AB55B5A630B24A2652C50B78141C00)
また、本記事の内容に深くご興味がある場合、インフラジスティックス・ジャパンのスタッフによる翻訳リクエストを受け付けておりますので、「JapanPR@infragistics.com」宛にご連絡ください。

以下に示すように、FormBuilder クラスを使用して作成されたリアクティブ フォームがあるとします。

ngOnInit() {
    this.loginForm = this.fb.group({
      email: [null, Validators.required],
      password: [null, [Validators.required, Validators.maxLength(8)]],
      phonenumber: [null]
    });

}

loginForm を作成しましょう。これには、電子メール、パスワード、電話番号の 3 つのコントロールがあります。ここでは、FormBuilder を使用してリアクティブ フォームを作成しています。コンポーネント テンプレートでは、以下のコード リストに示すように loginForm を添付できます。プロパティ バインディングを使用して、HTML フォーム要素の formGroup プロパティが loginForm に設定され、これらのコントロールの formControlName 値が FormBuilder の個々の FormControl プロパティに設定されます。

<form (ngSubmit)='loginUser()' [formGroup]='loginForm' novalidate class="form">
     <input formControlName='email' type="text" class="form-control" placeholder="Enter Email" />
     <div class="alert  alert-danger" *ngIf="loginForm.get('email').hasError('required') && loginForm.get('email').touched">
         Email is required
     </div>
     <input formControlName='password' type="password" class="form-control" placeholder="Enter Password" />
     <input formControlName='phonenumber' type="text" class="form-control" placeholder="Enter Phone Number" />
     <div class="alert  alert-danger" *ngIf="loginForm.get('phonenumber').hasError('required') && loginForm.get('phonenumber').touched">
         Phone Number is required
     </div>
     <br />
     <button [disabled]='loginForm.invalid' class="btn btn-default">Login</button>
 </form>

また、電子メールと電話番号のフィールドにエラーメッセージを表示しましょう。さらに、送信ボタンは、フォームが有効な場合にのみ有効になります。フォームの送信は、以下のリストに示すように処理されます。

loginUser() {
    console.log(this.loginForm.status);
    console.log(this.loginForm.value);
}

フォームがブラウザ コンソールで有効な場合、次のような出力が得られます。

さらに、エラーが発生した場合、送信ボタンが無効になり、エラーメッセージが次のように表示されます。

Angular Reactive Forms のカスタム バリデーターを作成する方法はこちら(英語ブログ)で学べます。

ここで、通知を送信するためのラジオ ボタンがあるシナリオを想定します。ユーザーは通知の送信オプションを選択できる必要があり、それに基づいて、特定の FormControl で検証が走るようにしましょう。

以下のフォームを検討してください。

通知の送信オプションを追加しました。ユーザーが通知を送信するために電話を選択した場合は、[電話番号] フィールドが必須となり、そうでない場合は必須ではなくなります。これを実現するには、次のタスクを実行する必要があります。

  1. 変更をリッスンする
  2. 条件付き検証を実装する

まず、通知を処理するようにフォームを変更しましょう。フォームには通知 FormControl があり、デフォルト値を null に設定すると、以下のようになります。

this.loginForm = this.fb.group({
    email: [null, Validators.required],
    password: [null, [Validators.required, Validators.maxLength(8)]],
    phonenumber: [null],
    notification: ['email']
});

リアクティブ フォーム テンプレートに、通知の送信オプションを処理するためのラジオ ボタン グループを追加します。

<form (ngSubmit)='loginUser()' [formGroup]='loginForm' novalidate class="form">
    <input formControlName='email' type="text" class="form-control" placeholder="Enter Email" />
    <div class="alert  alert-danger" *ngIf="loginForm.get('email').hasError('required') && loginForm.get('email').touched">
        Email is required
    </div>
    <input formControlName='password' type="password" class="form-control" placeholder="Enter Password" />
    <input formControlName='phonenumber' type="text" class="form-control" placeholder="Enter Phone Number" />
    <div class="alert  alert-danger" *ngIf="loginForm.get('phonenumber').hasError('required') && loginForm.get('phonenumber').touched">
        Phone Number is required
    </div>
    <br />
    <label class='control-label'>Send Notification</label>
    <br />
    <label class="radio-inline">
        <input type="radio" value="email" formControlName="notification">Email
    </label>
    <label class="radio-inline">
        <input type="radio" value="phone" formControlName="notification">Phone
    </label>
 
    <br />
    <button [disabled]='loginForm.invalid' class="btn btn-default">Login</button>
</form>

この時点で、フォームは次のようになります。

valueChanges を購読 (サブスクライブ) する

リアクティブ フォームでは、FormControls と FormGroups の両方に valueChanges メソッドがあります。これは監視可能なタイプを返しますので、購読することで FormControls または FormGroups のリアルタイムの値変更を処理できるようになります。

今回の例では、通知 FormControl の valueChanges を購読する必要があります。これは次のように実装できます。

formControlValueChanged() {
    this.loginForm.get('notification').valueChanges.subscribe(
        (mode: string) => {
            console.log(mode);
        });
}

これを以下に示す OnInit ライフサイクルで呼び出す必要があります。

ngOnInit() {
    this.loginForm = this.fb.group({
        email: [null, Validators.required],
        password: [null, [Validators.required, Validators.maxLength(8)]],
        phonenumber: [null],
        notification: ['email']
    });

    this.formControlValueChanged();

}

これで、フォームで通知オプションを選択するとブラウザ コンソールに最新の値が表示されるようになりました。

最新の値を取得するためにラジオ ボタンでイベントを処理することはありません。Angular には valueChanges メソッドがあり、FormControl と FormGroup で監視可能な最新の値を返します。また、通知 FormControl で最新の値を購読します。

条件付き検証

私たちの要件は、通知が電話に設定されている場合、電話番号 FormControl は必須フィールドである必要があり、電子メールに設定されている場合、電話番号 FormControl は検証されないようにする必要があります。

次のリストに示すように formControlValueChnaged() 関数を変更して、電話番号 FormControl の条件付き検証を有効にしましょう。

formControlValueChanged() {
    
    const phoneControl = this.loginForm.get('phonenumber');
    this.loginForm.get('notification').valueChanges.subscribe(
        (mode: string) => {
            console.log(mode);
            if (mode === 'phone') {
                phoneControl.setValidators([Validators.required]);
            }
            else if (mode === 'email') {
                phoneControl.clearValidators();
            }
            phoneControl.updateValueAndValidity();
        });

}

上記のコードはたくさんあるので、1 行ずつ説明しましょう。

  1. FormBuilder の get メソッドを使用して、電話番号 FormControl のインスタンスを取得します
  2. 通知 FormControl で valueChanges メソッドを購読します
  3. 通知 FormControl の現在の値を確認します
  4. 現在の値が電話の場合、FormControl の setValidators メソッドを使用して、電話番号コントロールに必要なバリデーターを設定します
  5. 現在の値が電子メールの場合、FormControl の clearValidators メソッドを使用して、電話番号制御のすべての検証をクリアします
  6. 最後に updateValueAndValidity メソッドを呼び出して、phonecontrol の検証ルールを更新します

アプリケーションを実行し、通知オプションを変更すると、電話番号の検証が変更されていることがわかります。

Angular Reactive Form の valueChanges メソッドの機能を使用することで、条件付き検証や、リアクティブ フォームの基になるデータ モデルの変更への対応など、他の多くの機能を実現できます。

この記事はいかがでしたか?

この投稿が気に入ったら共有してください。 さらに、Infragistics Ignite UI for Angular をご参照ください。 30 以上のマテリアル ベースの Angular コンポーネントがあり、高速な Web アプリをより高速にコーディングできます。

[https://jp.infragistics.com/products/ignite-ui-angular/angular/components/general/getting-started#installation:embed:cite]