Angular 2 Form Group에서 모든 검증 오류를 가져옵니다.
이 코드를 지정하면:
this.form = this.formBuilder.group({
email: ['', [Validators.required, EmailValidator.isValid]],
hasAcceptedTerms: [false, Validators.pattern('true')]
});
어떻게 하면 모든 검증 오류를 얻을 수 있을까요?this.form
?
유닛 테스트를 쓰고 있는데 실제 검증 오류를 아사트 메시지에 포함시키고 싶습니다.
같은 문제가 발생하여 모든 검증 오류를 찾아 표시하기 위해 다음 방법을 썼습니다.
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(..)
필요한 만큼만.
이 솔루션은 다음과 같은 방법으로 해결 방법:FormGroup
내부 지지대(여기 참조)
테스트 대상: 각도 4.3.6
get-form-validation-displays.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;
}
Angular 양식에서 모든 오류를 검색하는 재귀적 방법, 공식 구조를 만든 후에는 양식에서 모든 오류를 검색할 수 없습니다.이는 디버깅 목적뿐만 아니라 이러한 오류를 표시하는 데도 매우 유용합니다.
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;
}
}
이는 에러를 재귀적으로 수집하는 또 다른 변종이며 다음과 같은 외부 라이브러리에 의존하지 않습니다.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;
}
}
또는 이 라이브러리를 사용하여 깊고 역동적인 형식에서도 모든 오류를 가져올 수 있습니다.
npm i @naologic/forms
자신의 양식에서 정적 기능을 사용하려면
import {NaoFormStatic} from '@naologic/forms';
...
const errorsFlat = NaoFormStatic.getAllErrorsFlat(fg);
console.log(errorsFlat);
사용하고 싶은 경우NaoFromGroup
Import하여 사용할 수 있습니다.
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"}}
매뉴얼 전문을 읽다
@Mixer 기반OID 응답: 컴포넌트로서의 최종 솔루션을 다음에 나타냅니다(라이브러리를 작성할 수도 있습니다).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>
[ Try This ]그럼 형식에서 모든 컨트롤에 대한 검증이 호출됩니다.
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);
}
});
}
Andreas 코드를 사용하여 플랫오브젝트 내의 모든 에러 코드를 취득하여 표시되는 에러를 보다 쉽게 로깅할 수 있도록 조정했습니다.
다음 사항을 고려하십시오.
export function collectErrors(control: AbstractControl): any | null {
let errors = {};
let recursiveFunc = (control: AbstractControl) => {
if (isFormGroup(control)) {
return Object.entries(control.controls).reduce(
(acc, [key, childControl]) => {
const childErrors = recursiveFunc(childControl);
if (childErrors) {
if (!isFormGroup(childControl)) {
errors = { ...errors, [key]: childErrors };
}
acc = { ...acc, [key]: childErrors };
}
return acc;
},
null
);
} else {
return control.errors;
}
};
recursiveFunc(control);
return errors;
}
이.form.errors 속성을 반복할 수 있습니다.
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;
}
}
데보라크에서 가져와서 조금 수정했어요
// 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);
수락된 응답을 조정하여 문자열을 반환하고, 이 문자열은 콘솔에 인쇄할 수 있습니다.
function getFormValidationErrors(form: FormGroup): string {
return Object.keys(form.controls)
.map((control) => {
const controlErrors = form.get(control).errors;
if (!controlErrors) {
return [];
}
const controlErrorsString = Object.keys(controlErrors)
.flatMap(
(keyError) => `${keyError}: ${controlErrors[keyError]}`
)
.join(', ');
return `${control}: {${controlErrorsString}}`;
})
.filter((list) => list.length > 0)
.join('\n');
}
대형 Form Group 트리의 경우 lodash를 사용하여 트리를 정리하고 오류가 있는 컨트롤만 트리를 가져올 수 있습니다.이는 하위 제어를 통해 반복됨으로써 이루어집니다(예: 사용).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;
}
}
**I met the same problem and for finding all validation errors and
displaying only first error, I wrote next method:**
> first declare variable on top
public errors: any = [];
public fieldError: any = '';
> now subscribe form on noOnInit
this.form.valueChanges.subscribe(() => {
this.showOnlyFirstError(this.form);
this.errors = []
});
this.showOnlyFirstError(this.form);
> now call function
showOnlyFirstError(form) {
Object.keys(form.controls).forEach(key => {
const controlErrors: ValidationErrors = form.get(key).errors;
if (controlErrors != null) {
Object.keys(controlErrors).forEach(keyError => {
const showMessage = key + " is " + keyError
this.errors.push(showMessage)
this.fieldError = this.errors[0]
});
}
});
}
FormControls, FromGroups 및 FormArrays를 포함하는 매우 복잡한 FormGroup 컨트롤의 모든 오류를 제시해야 합니다.
간단한 솔루션을 작성하려고 했지만 모든 유형의 컨트롤을 지원하는 완벽한 솔루션을 찾을 수 없어서 다음과 같은 간단한 재귀 함수를 개발하여 모든 솔루션과 공유 중입니다.
export interface FieldError {
formGroupName: string;
fieldName: string;
errorCode: string;
}
export function getFormErrors(
control: AbstractControl,
formGroupName: string,
fieldName: string,
errors: FieldError[]) {
if (control instanceof FormGroup) {
Object.keys(control.controls).forEach(controlName => {
let formControl = control.get(controlName);
if (formControl) {
let fGroupName = formGroupName + "-" + controlName;
getFormErrors(formControl, fGroupName, controlName, errors);
}
})
}
if (control instanceof FormArray) {
control.controls.forEach((fControl: AbstractControl, index) => {
let fGroupName = formGroupName + "-" + index;
getFormErrors(fControl, fGroupName, "Array", errors);
})
}
if (control instanceof FormControl) {
const controlErrors: ValidationErrors | null = control.errors;
if (controlErrors) {
Object.keys(controlErrors).forEach(errorCode => {
errors.push({
formGroupName: formGroupName,
fieldName: fieldName,
errorCode: errorCode
})
});
}
}
}
사용 방법은 다음과 같습니다.
let errors: FieldError[] = []
getFormErrors(YOUR_FORM_GROUP, "root", "", errors);
저는 angular 5를 사용하고 있으며, Form Group을 사용하여 폼의 상태 속성을 간단히 확인할 수 있습니다.
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는 "INVALID"가 됩니다.
가장 좋은 점은 실시간으로 변화를 감지한다는 것입니다.
언급URL : https://stackoverflow.com/questions/40680321/get-all-validation-errors-from-angular-2-formgroup
'programing' 카테고리의 다른 글
Wordpress - 편집기에 html/텍스트 삽입 (0) | 2023.03.18 |
---|---|
ngpattern을 사용하여 자연 입력 번호 확인 (0) | 2023.03.08 |
변경의 원인이 되는 클릭 이벤트와 관련된 ng-repeat 항목을 애니메이션화하는 방법 (0) | 2023.03.08 |
ng-upload를 사용하여 이미지를 업로드하는 AngularJS (0) | 2023.03.08 |
임의의 JSON을 DOM에 삽입하기 위한 베스트 프랙티스 (0) | 2023.03.08 |