コンテンツへスキップ
AngularリアクティブフォームのvalueChangesメソッドの条件付き検証

AngularリアクティブフォームのvalueChangesメソッドの条件付き検証

Reactive Formsの値変更検出の使用方法Angularご存知ですか?このブログ投稿では、その方法をご紹介します。

6min read

このブログ投稿では、リアクティブフォームAngular値変更検出を使用し、それに基づいて条件付き検証を有効にする方法を学び、最高かつ最も完全なAngularコンポーネントライブラリであるIgnite UIを使用します。

最初のAngularリアクティブフォームの作成方法については、こちらをご覧ください。

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

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

  }

電子メール、パスワード、電話番号の 3 つのコントロールを持つ loginForm を作成しました。ここでは、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こちらで学ぶことができます。

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

以下のフォームを考えてみましょう。

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

  1. 変更を聞く
  2. Put conditional validation

まず、通知を処理するようにフォームを変更しましょう。これで、フォームには、以下のリストに示すように、デフォルト値がnullに設定された通知FormControlがあります。

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には、FormControlとFormGroupで監視可能な最近の値を返すvalueChangesメソッドがあり、通知FormControlの最近の値に対してそれをサブスクライブしています。

Conditional Validation

私たちの要件は、通知が phone に設定されている場合は、電話番号 FormControl を必須フィールドにし、email に設定されている場合は、電話番号 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. FormBuilderのgetメソッドを使って電話番号FormControlのインスタンスを取得する
  2. 通知 FormControl の valueChanges メソッドのサブスクライブ
  3. 通知 FormControl の現在の値を確認する
  4. 現在の値が電話の場合、FormControl の setValidators メソッドを使用して、電話番号コントロールに必要なバリデーターを設定します。
  5. 現在の値が電子メールの場合、FormControl の clearValidators メソッドを使用して、電話番号コントロールのすべての検証をクリアします
  6. 最後にupdateValueAndValidityメソッドを呼び出してphonecontrolの検証ルールを更新します

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

アプリケーションを実行すると、通知値を変更すると表示されます

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

この投稿が好きですか?

この投稿が気に入ったら、共有してください。また、まだライブラリをチェックアウトしていない方は、ぜひチェックアウトしてください。これは、マテリアルベースのUIコンポーネント、市場で最速のAngularデータグリッド、および60 +高性能チャートを備えた最も完全なツールボックスです。

 

Ignite UI for Angular利点

デモを予約