web-dev-qa-db-ja.com

Angular2リアクティブフォームは、検証失敗条件に基づいてエラーメッセージを表示します

エラーを表示するために個別の汎用コンポーネントを使用していることを言及したいので、繰り返しを避けるためにそれらをhtml内に直接入れていないので、テンプレートで条件を直接チェーンおよびハードコードすることはできません。

このフィールドと2つの検証が適用されています。

this.username = new FormControl('', [ Validators.minLength(5), Validators.required ]); 

検証ごとに検証エラーメッセージを表示するにはどうすればよいですか?送信時にフィールドに何もない場合、両方のエラーを表示するとします。
「最小長は5」
"フィールドは必須です"

そして、中に何かを置くと、表示されるだけです:
「最小長は5」

これは例ですが、私の実際の例では、2つの電子メールフィールドが同じである場合に比較するため、電子メールが正しくない場合は次のように表示されます。
「メールが正しくありません」
"メールは最初のメールフィールドとは異なります"

そのため、電子メールが正しく、電子メールが同じでない場合は、次のもののみが表示されます。
「電子メールは最初の電子メールフィールドと同じではありません」

合格しなかった場合は検証が機能しますが、検証が成功した場合とそうでない場合を別々に表示する方法がわかりません。失敗した本当の理由を適切に追加し、両方の一般的な理由を入れないでください。

完全な例:

エラー表示用のコンポーネント:

import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'app-field-error-display',
  templateUrl: './field.error.display.component.html',
  styleUrls: ['./field.error.display.component.css']
})
export class FieldErrorDisplayComponent
{
    @Input() errorMsg: string;
    @Input() displayError: boolean;
}

コンポーネントhtml:

<div *ngIf="displayError" >
  <small>{{errorMsg}}</small>
</div>

Register.htmlでのerorr表示の使用法:

<form [formGroup]="_form" (ngSubmit)="register()">
<h4>Create a new account</h4>
<div class="form-group">
  <label for="email">Email Address</label>
  <input class="form-control" name="email" formControlName="email" />
  <app-field-error-display [displayError]="formValidationService.IsFieldValid(_form,'email')" errorMsg="Please insert correct email"></app-field-error-display>
</div>
<div class="form-group">
  <label for="emailConfirm">Email Address Confirm</label>
  <input class="form-control" name="emailConfirm" formControlName="emailConfirm" />
  <app-field-error-display [displayError]="formValidationService.IsFieldValid(_form,'emailConfirm')" errorMsg="Please insert correct email"></app-field-error-display>
</div>
<div class="form-group">
  <label for="password">Password</label>
  <input class="form-control" name="password" formControlName="password" />
  <app-field-error-display [displayError]="formValidationService.IsFieldValid(_form,'password')" errorMsg="Please insert password"></app-field-error-display>
</div>
<button type="submit" class="btn btn-default">Create Account</button>
</form>
<div *ngIf="_registered" class="alert alert-success box-msg" role="alert">
  <strong>Account registered!</strong> You will be redirected in sec
</div>

コンポーネントの登録:

ngOnInit() {
    this._form = this._formBuilder.group({
        email: ['', [Validators.required, Validators.email]],
        emailConfirm: ['', [Validators.required, Validators.email, MatchOtherValidator.Validate('email')]],
        password: ['', [Validators.required]]
    });

    this._registerModel = new RegisterModel();
}

カスタムマッチのその他のバリデータ:

import { FormControl } from '@angular/forms';

export class MatchOtherValidator {
    static Validate(otherControlName: string) {

        let thisControl: FormControl;
        let otherControl: FormControl;

        return function matchOtherValidate(control: FormControl) {

            if (!control.parent) {
                return null;
            }

            // Initializing the validator.
            if (!thisControl) {
                thisControl = control;
                otherControl = control.parent.get(otherControlName) as FormControl;
                if (!otherControl) {
                    throw new Error('matchOtherValidator(): other control is not found in parent group');
                }
                otherControl.valueChanges.subscribe(() => {
                    thisControl.updateValueAndValidity();
                });
            }

            if (!otherControl) {
                return null;
            }

            if (otherControl.value !== thisControl.value) {
                return {
                    matchOther: true
                };
            }

            return null;

        }
    }
}

フォーム検証サービスには次のメソッドがあります。

public IsFieldValid(form: FormGroup, field: string){
    return !form.get(field).valid && form.get(field).dirty;
}
9
sensei

コードは、フォームコントロールが汚れて無効であるかどうかのみをチェックします。ただし、特定の検証が失敗したかどうかを確認する必要があります。したがって、追加のerror引数( 'required'、 'minlength'など)を渡す必要があります。

form.get(field).hasError(error)
16
JB Nizet

私はこれに少し遅れて答えていますが、私が本当に好きだったangularマテリアルモジュールの一部であるソリューションを見つけました。 "mat-form-field"を使用してフィールドを実装すると、 * ngIfを持つスパンを含む「mat-error」を使用して、エラーメッセージを簡単に表示します。

バリデーターエラーメッセージを実装しようとしている他の人々のためにそこにそれを置くべきだと考えました。 HTMLを少し強化しますが、見た目はとてもいいです。

<form [formGroup]="myForm" (ngSubmit)="submitForm()">
        <mat-form-field>
            <input matInput formControlName="user_input">
            <mat-error>
                <span *ngIf="myForm?.controls.user_input?.errors?.required">Required Field</span>
                <span *ngIf="myForm?.controls.user_input?.errors?.minLength">Minimum Length is 5</span>
            </mat-error>
        </mat-form-field>
</form>

ドキュメントはここにあります: https://material.angular.io/components/form-field/overview#error-messages

12
Logan Kitchen

カスタムバリデーターのマッチその他が失敗した場合、{match Other:true}を返してform.get(field).hasError('matchOther');をチェックする必要があります

1
Ankit Raonka