Diberikan kode ini:
this.form = this.formBuilder.group({
email: ['', [Validators.required, EmailValidator.isValid]],
hasAcceptedTerms: [false, Validators.pattern('true')]
});
Bagaimana saya bisa mendapatkan semua kesalahan validasi this.form
?
Saya sedang menulis pengujian unit dan ingin memasukkan kesalahan validasi aktual dalam pesan assert.
angular
typescript
validation
EagleBeak
sumber
sumber
Jawaban:
Saya menemui masalah yang sama dan untuk menemukan semua kesalahan validasi dan menampilkannya, saya menulis metode selanjutnya:
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]); }); } }); }
Nama formulir
productForm
harus diubah menjadi milik Anda.Ini bekerja dengan cara berikutnya: kita mendapatkan semua kontrol kita dari formulir dalam format
{[p: string]: AbstractControl}
dan diulangi oleh setiap kunci kesalahan, untuk mendapatkan detail kesalahan. Ini melewatkannull
nilai kesalahan.Ini juga dapat diubah untuk menampilkan kesalahan validasi pada tampilan templat, cukup ganti
console.log(..)
dengan yang Anda butuhkan.sumber
' + controlErrors[keyErrors];
bukan', controlErrors[keyErrors];
?ValidationErrors
di angular 2?import { ValidationErrors } from '@angular/forms';
Ini adalah solusi dengan
FormGroup
dukungan dari dalam ( seperti di sini )Dites pada: Angular 4.3.6
get-form-validation-error.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; }
Menggunakan contoh :
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; }
sumber
controlErrors
yaituif (controlErrors) {
karena hanya memeriksanull
akan memberikan kesalahan jika ada kesalahanundefined
Ini adalah varian lain yang mengumpulkan kesalahan secara rekursif dan tidak bergantung pada pustaka eksternal seperti
lodash
(hanya 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; } }
sumber
Cara rekursif untuk mengambil semua kesalahan dari bentuk Angular , setelah membuat segala jenis struktur formularium, tidak ada cara untuk mengambil semua kesalahan dari formulir. Ini sangat berguna untuk tujuan debugging tetapi juga untuk merencanakan kesalahan tersebut.
Diuji untuk Angular 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; } }
sumber
form.errors ?? null
Saya harus menghapus ?? untuk dikompilasi. Lebih penting lagi, dalam kondisi cek FormGroup, saya menambahkan|| formParameter instanceof FormArray
yang benar-benar membuka aplikasi saya. Terima kasih!Atau Anda bisa menggunakan pustaka ini untuk mendapatkan semua kesalahan, bahkan dari bentuk yang dalam dan dinamis.
Jika Anda ingin menggunakan fungsi statis pada formulir Anda sendiri
import {NaoFormStatic} from '@naologic/forms'; ... const errorsFlat = NaoFormStatic.getAllErrorsFlat(fg); console.log(errorsFlat);
Jika Anda ingin menggunakan
NaoFromGroup
Anda dapat mengimpor dan menggunakannyaimport {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"}}
Baca dokumentasi lengkapnya
sumber
Berdasarkan tanggapan @MixerOID , berikut adalah solusi terakhir saya sebagai komponen (mungkin saya membuat perpustakaan). Saya juga mendukung 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; } } }
Dan HTML:
<div *ngIf="formRef.submitted"> <div *ngFor="let error of errors" class="text-danger"> {{getErrorMessage(error)}} </div> </div>
Pemakaian:
<app-form-errors [form]="languageForm" [formRef]="formRef" [messages]="{language: 'Language'}"> </app-form-errors>
sumber
Coba Ini, ini akan memanggil validasi untuk semua kontrol dalam bentuk:
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); } }); }
sumber
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; } }
Saya mengambilnya dari Deborahk dan mengubahnya sedikit.
sumber
// 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);
sumber
Anda dapat mengulang properti this.form.errors.
sumber
this.form.errors
hanya mengembalikan kesalahan validasi untukthis.form
, bukan untukthis.form.controls
. Anda dapat memvalidasi FormGroups dan turunannya (sembarang jumlah FormGroups, FormControls dan FormArrays) secara terpisah. Untuk mengambil semua kesalahan, saya pikir Anda perlu menanyakannya secara rekursif.Untuk pohon FormGroup yang besar, Anda dapat menggunakan lodash untuk membersihkan pohon dan mendapatkan pohon hanya dari kontrol dengan kesalahan. Ini dilakukan dengan mengulang melalui kontrol anak (misalnya menggunakan
allErrors(formGroup)
), dan memangkas subkelompok kontrol yang sepenuhnya valid: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; } }
sumber
Saya menggunakan angular 5 dan Anda cukup memeriksa properti status formulir Anda menggunakan mis. FormGroup
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]) });
this.form.status akan menjadi "INVALID" kecuali semua kolom lolos semua aturan validasi.
Bagian terbaiknya adalah mendeteksi perubahan secara real-time.
sumber