在Angular(v2 onwards) reactive form Form Array 中获取无效控件
Get the invalid control in Angular(v2 onwards) reactive form Form Array
this.from.valid returns false 我正在使用下面的这种方法来获取第一个无效控件并在我的组件中相应地抛出错误。这种方法在没有任何表单数组的情况下可以很好地处理表单组。
有没有办法找出Form Array的第一个无效控件
获取表单验证-errors.ts
import {
AbstractControl,
FormArray,
FormGroup,
ValidationErrors
} from '@angular/forms';
export interface AllValidationErrors {
control_name: string;
error_name: string;
error_value: any;
control_modified: string;
}
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));
control.markAsTouched({
onlySelf: true
});
} else if (control instanceof FormArray) {
for (const arrayControl of control.controls) {
if (arrayControl instanceof FormGroup) {
errors = errors.concat(
getFormValidationErrors(arrayControl.controls)
);
}
}
}
const controlErrors: ValidationErrors = controls[key].errors;
if (controlErrors !== null) {
Object.keys(controlErrors).forEach((keyError) => {
errors.push({
control_name: key,
error_name: keyError,
control_modified: beautifyControl(key),
error_value: controlErrors[keyError]
});
});
}
});
return errors;
}
function beautifyControl(key: string): string {
let result: string[] = [];
const splitters = ['-', '_'] as const;
if (key.includes(splitters[0])) result = key.split(splitters[0]);
else if (key.includes(splitters[1])) result = key.split(splitters[1]);
else result = key.replace(/([a-z])([A-Z])/g, ' ').split(' ');
return [
...result.map((e: string, i: number) => e[0].toUpperCase() + e.slice(1))
].join(' ');
}
使用示例:
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;
}
我觉得当 FormArray 是 FormControls 的 FormArray 时你需要考虑,所以应该像
Object.keys(controls).forEach((key) => {
const control = controls[key];
if (control instanceof FormGroup) {
errors = errors.concat(getFormValidationErrors(control.controls));
control.markAsTouched({
onlySelf: true
});
} else if (control instanceof FormArray) {
for (const arrayControl of control.controls) {
//..call to your function directly..
errors = errors.concat(
getFormValidationErrors(arrayControl.controls)
}
}
...
所以你需要
Object.keys(controls).forEach(key => {
const control = controls[key];
if (control instanceof FormGroup) {
...
} else if (control instanceof FormArray) {
let i: number = 0;
for (const arrayControl of control.controls) {
if (arrayControl instanceof FormGroup) {
...
} else { //add the case if the FormArray is a FormArray
//of a FormControls
const obj = {};
obj[key + '-' + i] = arrayControl;
i++;
errors = errors.concat(getFormValidationErrors(obj));
}
}
}
我写的又傻又丑stackblitz
this.from.valid returns false 我正在使用下面的这种方法来获取第一个无效控件并在我的组件中相应地抛出错误。这种方法在没有任何表单数组的情况下可以很好地处理表单组。
有没有办法找出Form Array的第一个无效控件
获取表单验证-errors.ts
import {
AbstractControl,
FormArray,
FormGroup,
ValidationErrors
} from '@angular/forms';
export interface AllValidationErrors {
control_name: string;
error_name: string;
error_value: any;
control_modified: string;
}
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));
control.markAsTouched({
onlySelf: true
});
} else if (control instanceof FormArray) {
for (const arrayControl of control.controls) {
if (arrayControl instanceof FormGroup) {
errors = errors.concat(
getFormValidationErrors(arrayControl.controls)
);
}
}
}
const controlErrors: ValidationErrors = controls[key].errors;
if (controlErrors !== null) {
Object.keys(controlErrors).forEach((keyError) => {
errors.push({
control_name: key,
error_name: keyError,
control_modified: beautifyControl(key),
error_value: controlErrors[keyError]
});
});
}
});
return errors;
}
function beautifyControl(key: string): string {
let result: string[] = [];
const splitters = ['-', '_'] as const;
if (key.includes(splitters[0])) result = key.split(splitters[0]);
else if (key.includes(splitters[1])) result = key.split(splitters[1]);
else result = key.replace(/([a-z])([A-Z])/g, ' ').split(' ');
return [
...result.map((e: string, i: number) => e[0].toUpperCase() + e.slice(1))
].join(' ');
}
使用示例:
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;
}
我觉得当 FormArray 是 FormControls 的 FormArray 时你需要考虑,所以应该像
Object.keys(controls).forEach((key) => {
const control = controls[key];
if (control instanceof FormGroup) {
errors = errors.concat(getFormValidationErrors(control.controls));
control.markAsTouched({
onlySelf: true
});
} else if (control instanceof FormArray) {
for (const arrayControl of control.controls) {
//..call to your function directly..
errors = errors.concat(
getFormValidationErrors(arrayControl.controls)
}
}
...
所以你需要
Object.keys(controls).forEach(key => {
const control = controls[key];
if (control instanceof FormGroup) {
...
} else if (control instanceof FormArray) {
let i: number = 0;
for (const arrayControl of control.controls) {
if (arrayControl instanceof FormGroup) {
...
} else { //add the case if the FormArray is a FormArray
//of a FormControls
const obj = {};
obj[key + '-' + i] = arrayControl;
i++;
errors = errors.concat(getFormValidationErrors(obj));
}
}
}
我写的又傻又丑stackblitz