web-dev-qa-db-fra.com

Les formulaires réactifs Angular2 affichent des messages d'erreur basés sur la condition d'échec de la validation

Je tiens à mentionner que j'utilise des composants génériques distincts pour afficher les erreurs. Je ne les mets donc pas directement à l'intérieur du code HTML pour éviter les répétitions. Je ne peux donc pas chaîner et coder en dur directement dans le modèle.

J'ai ce champ et deux validations appliquées:

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

Comment afficher un message d'erreur de validation pour chacune des validations? Disons que je veux montrer les deux erreurs si rien n'est dans le champ lors de l'envoi:
"La longueur minimale est de 5"
"Champ requis"

Et puis, si vous mettez quelque chose à l'intérieur, il ne devrait afficher que:
"La longueur minimale est de 5"

Ceci est un exemple, mais mon exemple réel compare deux champs d’email, s’ils sont identiques, donc si l’email n’est pas correct, il devrait afficher:
"L'email n'est pas correct"
"Le courrier électronique est différent du premier champ de courrier électronique"

Donc, si le courrier électronique est correct et que les courriers électroniques ne sont pas les mêmes, vous ne devez afficher que:
"Le courrier électronique n’est pas identique au premier champ de courrier électronique"

J'ai des validations qui fonctionnent si elles ne sont pas réussies, mais je ne sais pas comment indiquer séparément si une validation est validée et une autre non, car je dois correctement annexer la véritable raison de son échec et ne pas indiquer de motif générique pour les deux.

Exemple complet:

Composant pour l'affichage d'erreur:

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;
}

Composant html:

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

Utilisation de erorr display dans Register.html:

<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>

Composant de registre:

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();
}

Match personnalisé autre validateur:

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;

        }
    }
}

Le service de validation de formulaire utilise cette méthode:

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

Votre code vérifie uniquement si le contrôle de formulaire est sale et non valide. Mais vous voulez vérifier si une validation spécifique échoue. Il faut donc passer un argument supplémentaire error ('required', 'minlength', etc.) et utiliser

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

Je réponds un peu tard, mais j'ai trouvé une solution qui fait partie des modules de matériaux angulaires que j'ai beaucoup aimés. Si vous implémentez vos champs à l'aide de "mat-form-field", vous pouvez facilement afficher les messages d'erreur à l'aide d'un "mat-error" contenant des étendues avec un * ngIf. 

J'ai pensé que je devrais le publier pour les autres personnes essayant d'implémenter les messages d'erreur du validateur. Cela rend le HTML un peu costaud mais il a vraiment l’air sympa.

<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>

La documentation se trouve ici: https://material.angular.io/components/form-field/overview#error-messages

7
Logan Kitchen

si le validateur personnalisé correspond à Other échoue, vous devez renvoyer {match Other: true} et cocher form.get(field).hasError('matchOther'); 

1
Ankit Raonka