सभी सत्यापन त्रुटियों को कोणीय 2 फॉर्मग्रुप से प्राप्त करें


92

इस कोड को दिया:

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

मैं सभी सत्यापन त्रुटियों को कैसे प्राप्त कर सकता हूं this.form?

मैं यूनिट परीक्षण लिख रहा हूं और वास्तविक सत्यापन त्रुटियों को मुखर संदेश में शामिल करना चाहता हूं।


Validators.pattern ('true') के बजाय आप जाँच की जा रही चेकबॉक्स को लागू करने के लिए Validators.requiredTrue का उपयोग कर सकते हैं।
शून्य

जवाबों:


146

मैं एक ही समस्या से मिला और सभी सत्यापन त्रुटियों को खोजने और उन्हें प्रदर्शित करने के लिए, मैंने अगली विधि लिखी:

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

फॉर्म का नाम productFormआपके लिए बदल दिया जाना चाहिए।

यह अगले तरीके से काम करता है: हम {[p: string]: AbstractControl}त्रुटि के विवरण प्राप्त करने के लिए अपने सभी नियंत्रणों को प्रारूप में और प्रत्येक त्रुटि कुंजी द्वारा पुन: व्यवस्थित करते हैं। यह nullत्रुटि मानों को छोड़ देता है।

इसे टेम्प्लेट दृश्य पर सत्यापन त्रुटियों को प्रदर्शित करने के लिए भी बदला जा सकता है, बस console.log(..)आपको जो चाहिए उसकी जगह लें ।


2
एक ही पैटर्न में FormArray के लिए उपरोक्त विधि का विस्तार कैसे करें?
मोहम्मद शराफ अली

क्या ' + controlErrors[keyErrors];इसके बजाय आपका मतलब था ', controlErrors[keyErrors];?
राणीम

@ आर्यनम नहीं, वस्तु की तरह मुद्रण में, या स्ट्रिंग मान की तरह अलग है।
एलेक्स एफिमोव

मैं ValidationErrorsकोणीय 2 में कहां से आयात कर सकता हूं ?
साेनू

import { ValidationErrors } from '@angular/forms';
क्रेग वेन

31

यह FormGroupअंदर के समर्थन के साथ समाधान है ( जैसे यहां )

पर परीक्षण किया: कोणीय 4.3.6

मिल-फार्म सत्यापन-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;
}

उदाहरण का उपयोग करना :

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

1
कोणीय 5 परिवर्तन - const controlErrors: ValidationErrors = form.controls [key] .errors;
क्रिश किलटन

सुझाव पर truthy के लिए जाँच करने के लिए controlErrors यानी if (controlErrors) {की जाँच के लिए ही के रूप में nullएक त्रुटि दे देंगे है, तो त्रुटियोंundefined
mtholen

8

यह एक और संस्करण है जो त्रुटियों को पुन: एकत्रित करता है और किसी भी बाहरी पुस्तकालय पर निर्भर नहीं करता है जैसे lodash(केवल ES6):

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

6

सभी प्रकार की त्रुटियों को एक कोणीय रूप से प्राप्त करने के लिए पुनरावर्ती तरीका , किसी भी प्रकार की सूत्र संरचना बनाने के बाद फॉर्म से सभी त्रुटियों को प्राप्त करने का कोई तरीका नहीं है। यह डिबगिंग उद्देश्यों के लिए बहुत उपयोगी है, लेकिन उन त्रुटियों की साजिश रचने के लिए भी।

कोणीय 9 के लिए परीक्षण किया गया

getFormErrors(form: AbstractControl) {
    if (form instanceof FormControl) {
        // Return FormControl errors or null
        return form.errors ?? null;
    }
    if (form instanceof FormGroup) {
        const groupErrors = form.errors;
        // Form group can contain errors itself, in that case add'em
        const formErrors = groupErrors ? {groupErrors} : {};
        Object.keys(form.controls).forEach(key => {
            // Recursive call of the FormGroup fields
            const error = this.getFormErrors(form.get(key));
            if (error !== null) {
                // Only add error if not null
                formErrors[key] = error;
            }
        });
        // Return FormGroup errors or null
        return Object.keys(formErrors).length > 0 ? formErrors : null;
    }
}

मैं कोणीय 7 का उपयोग कर रहा हूं और आपके कोड में दो संशोधन किए हैं: form.errors ?? nullमुझे हटाना पड़ा ?? इसके संकलन के लिए। इससे भी महत्वपूर्ण बात, फॉर्मग्रुप चेक स्थिति में, मैंने जोड़ा || formParameter instanceof FormArrayजो वास्तव में मेरे आवेदन को खोल देता है। धन्यवाद!
टायलर फोर्सिथे

6

या आप इस लाइब्रेरी का उपयोग सभी त्रुटियों को प्राप्त करने के लिए कर सकते हैं, यहां तक ​​कि गहरे और गतिशील रूपों से भी।

npm i @naologic/forms

यदि आप अपने स्वयं के रूपों पर स्थिर फ़ंक्शन का उपयोग करना चाहते हैं

import {NaoFormStatic} from '@naologic/forms';
...
const errorsFlat = NaoFormStatic.getAllErrorsFlat(fg); 
console.log(errorsFlat);

यदि आप उपयोग करना चाहते हैं NaoFromGroupतो आप इसे आयात और उपयोग कर सकते हैं

import {NaoFormGroup, NaoFormControl, NaoValidators} from '@naologic/forms';
...
    this.naoFormGroup = new NaoFormGroup({
      firstName: new NaoFormControl('John'),
      lastName: new NaoFormControl('Doe'),
      ssn: new NaoFormControl('000 00 0000', NaoValidators.isSSN()),
    });

   const getFormErrors = this.naoFormGroup.getAllErrors();
   console.log(getFormErrors);
   // --> {first: {ok: false, isSSN: false, actualValue: "000 00 0000"}}

पूरा प्रलेखन पढ़ें


2

@MixerOID प्रतिक्रिया के आधार पर , यहां एक घटक के रूप में मेरा अंतिम समाधान है (शायद मैं एक पुस्तकालय बनाता हूं)। मैं FormArray का भी समर्थन करता हूं:

import {Component, ElementRef, Input, OnInit} from '@angular/core';
import {FormArray, FormGroup, ValidationErrors} from '@angular/forms';
import {TranslateService} from '@ngx-translate/core';

interface AllValidationErrors {
  controlName: string;
  errorName: string;
  errorValue: any;
}

@Component({
  selector: 'app-form-errors',
  templateUrl: './form-errors.component.html',
  styleUrls: ['./form-errors.component.scss']
})
export class FormErrorsComponent implements OnInit {

  @Input() form: FormGroup;
  @Input() formRef: ElementRef;
  @Input() messages: Array<any>;

  private errors: AllValidationErrors[];

  constructor(
    private translateService: TranslateService
  ) {
    this.errors = [];
    this.messages = [];
  }

  ngOnInit() {
    this.form.valueChanges.subscribe(() => {
      this.errors = [];
      this.calculateErrors(this.form);
    });

    this.calculateErrors(this.form);
  }

  calculateErrors(form: FormGroup | FormArray) {
    Object.keys(form.controls).forEach(field => {
      const control = form.get(field);
      if (control instanceof FormGroup || control instanceof FormArray) {
        this.errors = this.errors.concat(this.calculateErrors(control));
        return;
      }

      const controlErrors: ValidationErrors = control.errors;
      if (controlErrors !== null) {
        Object.keys(controlErrors).forEach(keyError => {
          this.errors.push({
            controlName: field,
            errorName: keyError,
            errorValue: controlErrors[keyError]
          });
        });
      }
    });

    // This removes duplicates
    this.errors = this.errors.filter((error, index, self) => self.findIndex(t => {
      return t.controlName === error.controlName && t.errorName === error.errorName;
    }) === index);
    return this.errors;
  }

  getErrorMessage(error) {
    switch (error.errorName) {
      case 'required':
        return this.translateService.instant('mustFill') + ' ' + this.messages[error.controlName];
      default:
        return 'unknown error ' + error.errorName;
    }
  }
}

और HTML:

<div *ngIf="formRef.submitted">
  <div *ngFor="let error of errors" class="text-danger">
    {{getErrorMessage(error)}}
  </div>
</div>

उपयोग:

<app-form-errors [form]="languageForm"
                 [formRef]="formRef"
                 [messages]="{language: 'Language'}">
</app-form-errors>

2

इसे आज़माएं, यह फ़ॉर्म में सभी नियंत्रण के लिए सत्यापन कहेगा:

validateAllFormControl(formGroup: FormGroup) {         
  Object.keys(formGroup.controls).forEach(field => {  
    const control = formGroup.get(field);             
    if (control instanceof FormControl) {             
      control.markAsTouched({ onlySelf: true });
    } else if (control instanceof FormGroup) {        
      this.validateAllFormControl(control);            
    }
  });
}

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

मैंने इसे दबोरा से लिया और इसे थोड़ा संशोधित किया।


1
// IF not populated correctly - you could get aggregated FormGroup errors object
let getErrors = (formGroup: FormGroup, errors: any = {}) {
  Object.keys(formGroup.controls).forEach(field => {
    const control = formGroup.get(field);
    if (control instanceof FormControl) {
      errors[field] = control.errors;
    } else if (control instanceof FormGroup) {
      errors[field] = this.getErrors(control);
    }
  });
  return errors;
}

// Calling it:
let formErrors = getErrors(this.form);

0

आप इस पर सुधार कर सकते हैं।


14
मुझे लगता है कि this.form.errorsकेवल के लिए सत्यापन की त्रुटियों को लौटाता है this.form, के लिए नहीं this.form.controls। आप फॉर्मग्रुप्स और उसके बच्चों (फॉर्मग्रुप्स, फॉर्मकंट्रोल और फॉर्मअरेस की मनमानी संख्या) को अलग-अलग मान्य कर सकते हैं। सभी त्रुटियों को प्राप्त करने के लिए, मुझे लगता है कि आपको उन्हें पुनरावर्ती रूप से पूछने की आवश्यकता है।
रिस्तो वेल्लिमकी

0

एक बड़े फॉर्मग्रुप पेड़ के लिए, आप पेड़ को साफ करने के लिए लॉश का उपयोग कर सकते हैं और त्रुटियों के साथ बस नियंत्रण का पेड़ प्राप्त कर सकते हैं। यह बाल नियंत्रण (जैसे का उपयोग करके allErrors(formGroup)) के माध्यम से आवर्ती द्वारा किया जाता है , और नियंत्रण के किसी भी पूरी तरह से वैध उप समूहों को छंटनी:

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

// Returns a tree of any errors in control and children of control
allErrors(control: AbstractControl): any {
  if (this.isFormGroup(control)) {
    const childErrors = _.mapValues(control.controls, (childControl) => {
      return this.allErrors(childControl);
    });

    const pruned = _.omitBy(childErrors, _.isEmpty);
    return _.isEmpty(pruned) ? null : pruned;
  } else {
    return control.errors;
  }
}

-2

मैं कोणीय 5 का उपयोग कर रहा हूं और आप फॉर्मग्रुप जैसे का उपयोग करके बस अपने फॉर्म की स्थिति संपत्ति की जांच कर सकते हैं

this.form = new FormGroup({
      firstName: new FormControl('', [Validators.required, validateName]),
      lastName: new FormControl('', [Validators.required, validateName]),
      email: new FormControl('', [Validators.required, validateEmail]),
      dob: new FormControl('', [Validators.required, validateDate])
    });

जब तक सभी फ़ील्ड सभी सत्यापन नियमों को पारित नहीं करते हैं, तब तक यह "form.status "INVALID" होगा।

सबसे अच्छी बात यह है कि यह वास्तविक समय में परिवर्तनों का पता लगाता है।


1
हां, लेकिन हमें एक संपूर्ण फॉर्मग्रुप की त्रुटियों को प्राप्त करने की आवश्यकता है, न कि केवल यह पता है कि इसकी वैधता नहीं है
Motassem MK

ओपी को सत्यापन संदेशों की आवश्यकता है, जो स्थिति संपत्ति में शामिल नहीं हैं, क्योंकि यह सिर्फ एक बूलियन है।
स्टीफन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.