angular - 在 Angular(v2 及更高版本)反应形式表单数组中获取无效控件
问题描述
this.from.valid 返回 false 我正在使用下面的这种方法来获取第一个无效控件并在我的组件中相应地抛出错误。这种方法可以在没有任何表单数组的情况下工作良好的表单组。
有没有办法找出表单数组的第一个无效控件
获取表单验证错误.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, '$1 $2').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));
}
}
}
我写了一个愚蠢而丑陋的堆栈闪电战
推荐阅读
- swift - 如何从 string.index 中获取 Int?
- javafx - 为 TabPanes 选项卡使用 JavaFX PopOver 以查看其内容
- python-3.x - ipyparallel 推送一个元组以避免在每个引擎中加载它
- centos - 如何在 centos 7 上安装 Haxe
- c# - C# + VB:导入 reg 文件
- java - 由于响应中的错误结果,弹簧方法的 Mockito 测试失败
- c# - 如何删除一个sql数据行c#
- python - 在 python 中加载纽约大学深度 v2 数据集
- html - 相同的 HTML CSS 呈现不同,具体取决于单点登录
- bash - 从cygwin调用cmd / c时如何显示一行的彩色输出