140 votes

Obtenez toutes les erreurs de validation de Angular 2 FormGroup

Étant donné ce code:

 this.form = this.formBuilder.group({
      email: ['', [Validators.required, EmailValidator.isValid]],
      hasAcceptedTerms: [false, Validators.pattern('true')]
    });
 

Comment puis-je obtenir toutes les erreurs de validation de this.form ?

J'écris des tests unitaires et souhaite inclure les erreurs de validation réelles dans le message d'assertion.

240voto

Alex Efimov Points 988

J'ai rencontré le même problème et pour trouver toutes les erreurs de validation et de les afficher, j'ai écrit méthode suivante:

getFormValidationErrors() {
  Object.keys(this.productForm.controls).forEach(key => {

  const controlErrors: ValidationErrors = this.productForm.get(key).errors;
  if (controlErrors != null) {
        Object.keys(controlErrors).forEach(keyError => {
          console.log('Key control: ' + key + ', keyError: ' + keyError + ', err value: ', controlErrors[keyError]);
        });
      }
    });
  }

Nom du formulaire productForm doit être changé à la vôtre.

Il fonctionne de manière suivante: nous recevons tous nos contrôles de formulaire en format {[p: string]: AbstractControl} et de réitérer par chaque erreur de clé, pour obtenir les détails de l'erreur. Il saute null des valeurs d'erreur.

Il peut également être modifié pour afficher les erreurs de validation sur le modèle de la vue, il suffit de remplacer console.log(..) de ce que vous avez besoin.

42voto

MixerOID Points 900

C'est une solution avec FormGroup supports internes ( comme ici )

Testé sur: angulaire 4.3.6

get-form-validation-errors.ts

 import { AbstractControl, FormGroup, ValidationErrors } from '@angular/forms';

export interface AllValidationErrors {
  control_name: string;
  error_name: string;
  error_value: any;
}

export interface FormGroupControls {
  [key: string]: AbstractControl;
}

export function getFormValidationErrors(controls: FormGroupControls): AllValidationErrors[] {
  let errors: AllValidationErrors[] = [];
  Object.keys(controls).forEach(key => {
    const control = controls[ key ];
    if (control instanceof FormGroup) {
      errors = errors.concat(getFormValidationErrors(control.controls));
    }
    const controlErrors: ValidationErrors = controls[ key ].errors;
    if (controlErrors !== null) {
      Object.keys(controlErrors).forEach(keyError => {
        errors.push({
          control_name: key,
          error_name: keyError,
          error_value: controlErrors[ keyError ]
        });
      });
    }
  });
  return errors;
}
 

Exemple :

 if (!this.formValid()) {
  const error: AllValidationErrors = getFormValidationErrors(this.regForm.controls).shift();
  if (error) {
    let text;
    switch (error.error_name) {
      case 'required': text = `${error.control_name} is required!`; break;
      case 'pattern': text = `${error.control_name} has wrong pattern!`; break;
      case 'email': text = `${error.control_name} has wrong email format!`; break;
      case 'minlength': text = `${error.control_name} has wrong length! Required length: ${error.error_value.requiredLength}`; break;
      case 'areEqual': text = `${error.control_name} must be equal!`; break;
      default: text = `${error.control_name}: ${error.error_name}: ${error.error_value}`;
    }
    this.error = text;
  }
  return;
}
 

11voto

Andreas Klöber Points 2082

C'est une autre variante qui collecte les erreurs de manière récursive et ne dépend d'aucune bibliothèque externe telle que lodash (ES6 uniquement):

 function isFormGroup(control: AbstractControl): control is FormGroup {
  return !!(<FormGroup>control).controls;
}

function collectErrors(control: AbstractControl): any | null {
  if (isFormGroup(control)) {
    return Object.entries(control.controls)
      .reduce(
        (acc, [key, childControl]) => {
          const childErrors = collectErrors(childControl);
          if (childErrors) {
            acc = {...acc, [key]: childErrors};
          }
          return acc;
        },
        null
      );
  } else {
    return control.errors;
  }
}
 

7voto

Pian0_M4n Points 117

Ou vous pouvez simplement utiliser cette bibliothèque pour obtenir toutes les erreurs, même de profondes et des formes dynamiques.

npm install --save npm i @naologic/forms

Vous voudrez alors

import {SuperForm} from 'npm i @naologic/forms';

Puis il suffit de passer le FormGroup pour récupérer toutes vos erreurs

const errorsFlat = SuperForm.getAllErrorsFlat(fg); 
console.log(errorsFlat);

Mise à JOUR:

Vous pouvez utiliser npm i @naologic/forms et l'utilisation NaoFromGroup , au lieu de la forme classique du groupe angulaires. Il a quelques nouvelles fonctions, et vous pouvez également obtenir toutes les erreurs.

Désolé il n'y a pas de docs pourtant, il suffit de regarder le code.

Mise à JOUR:

la lib nécessite angulaire 6, car il utilise AbstractControlOptions

1voto

sasoft Points 68
 export class GenericValidator {
    constructor(private validationMessages: { [key: string]: { [key: string]: string } }) {
    }

processMessages(container: FormGroup): { [key: string]: string } {
    const messages = {};
    for (const controlKey in container.controls) {
        if (container.controls.hasOwnProperty(controlKey)) {
            const c = container.controls[controlKey];
            if (c instanceof FormGroup) {
                const childMessages = this.processMessages(c);
                // handling formGroup errors messages
                const formGroupErrors = {};
                if (this.validationMessages[controlKey]) {
                    formGroupErrors[controlKey] = '';
                    if (c.errors) {
                        Object.keys(c.errors).map((messageKey) => {
                            if (this.validationMessages[controlKey][messageKey]) {
                                formGroupErrors[controlKey] += this.validationMessages[controlKey][messageKey] + ' ';
                            }
                        })
                    }
                }
                Object.assign(messages, childMessages, formGroupErrors);
            } else {
                // handling control fields errors messages
                if (this.validationMessages[controlKey]) {
                    messages[controlKey] = '';
                    if ((c.dirty || c.touched) && c.errors) {
                        Object.keys(c.errors).map((messageKey) => {
                            if (this.validationMessages[controlKey][messageKey]) {
                                messages[controlKey] += this.validationMessages[controlKey][messageKey] + ' ';
                            }
                        })
                    }
                }
            }
        }
    }
    return messages;
}
}
 

Je l'ai pris à Deborahk et l' ai modifié un peu.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X