反应形式总是有效的,即使不是。窗体中的嵌套子项
Reactive Form Always Valid, Even When Not. Nested Children in Form
我已经看到一些关于这个问题的 Whosebug 问题,但其中 none 似乎已经证明了有效的答案。
我正在使用 Angular 构建一个动态创建的响应式表单。 StackBlitz here。用户可以选择在组内添加“组”和“条件”。每个组都可以使用 FormArrays 进一步嵌套。
表单按预期工作。以下是表格的主要部分:
- AppComponent:主要的父组件
- GroupControlComponent:父级的子级。照顾所有组对象
- ConditionFormComponent:GroupControlComponent 的子组件。照顾组内的所有条件
这是基本对象的样子:
{
// appcomponent level
"statement": {
//groupcontrol level
"groups": [
{
// conditionform level
"conjunctor": null,
"conditions": [
{
"variable": null
}
],
"groups": []
}
]
}
}
当我设置验证时,我希望一切都是必需的。所以我在父组件和子组件上浏览了 FormBuilder,并在所有表单控件上将 Validators.required
设置为 true。
this._fb.control({
conjunctor: null,
conditions: [[], Validators.required],
groups: [[], Validators.required]
})
(所有控件都是这样)
问题是,表格现在 总是 有效。即使表格实际上无效。是否可以在使用嵌套子组件时检查表单有效性?
如果需要,这里有一些关于这个特定表格的更多信息:
基本上您必须实现 Validator
(不是 Validators
- 复数)接口。它有一个强制方法:
validate(c: AbstractControl) => ValidationErrors;
如果控件有效,方法 validate
应该 return null
,如果控件无效,方法 validate
应该 null
。
还有一件事是您必须以与提供 NG_VALUE_ACCESSOR
.
相同的方式提供 NG_VALIDATORS
(现在,使用复数)
总结:
@Component({
...
providers: [
...
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => GroupControlComponent),
multi: true
}
]
})
export class GroupControlComponent implements Validator {
...
// Notice that we don't need to use the c parameter passed to the method.
// We are using the `_form` instance property to verify what we need
validate(c: AbstractControl): ValidationErrors {
return this._form.valid ? null : {errors: 'form is invalid'};
}
...
}
您必须对您的 GroupControlComponent
和 ConditionFormComponent
执行此操作。
[更新]:您还需要注意动态创建的控件。在组控件中,让我们看一下具有输入的单个组件:条件控件。而不是:
_addCondition() {
this._conditionsFormArray.push(
this._fb.control({variable: null})
);
}
您应该使用检查 variable
有效性的验证器来初始化控件,因为与 variable
属性关联的基础控件只会在用户与内部输入交互后才进行检查ConditionFormComponent
。所以,你应该这样写:
_addCondition() {
this._conditionsFormArray.push(
this._fb.control({variable: null},
(c: AbstractControl) =>
c.value && c.value.variable ? null : {'required': true}
)
);
}
这是检查 variable
属性有效性的验证函数:
(c: AbstractControl) =>
c.value && c.value.variable ? null : {'required': true}
如果您不这样做,它将覆盖底层 ConditionForm
控件中的验证(表明需要输入)。您可能会遇到一种奇怪的状态,即外部形式(在 GroupControl
中)无效,但内部形式(在 ConditionForm
中)有效。当您在外部表单上验证它时,您基本上甚至可以删除内部表单中的 Validators.required
并仅依赖外部表单验证。
我已经看到一些关于这个问题的 Whosebug 问题,但其中 none 似乎已经证明了有效的答案。
我正在使用 Angular 构建一个动态创建的响应式表单。 StackBlitz here。用户可以选择在组内添加“组”和“条件”。每个组都可以使用 FormArrays 进一步嵌套。
表单按预期工作。以下是表格的主要部分:
- AppComponent:主要的父组件
- GroupControlComponent:父级的子级。照顾所有组对象
- ConditionFormComponent:GroupControlComponent 的子组件。照顾组内的所有条件
这是基本对象的样子:
{
// appcomponent level
"statement": {
//groupcontrol level
"groups": [
{
// conditionform level
"conjunctor": null,
"conditions": [
{
"variable": null
}
],
"groups": []
}
]
}
}
当我设置验证时,我希望一切都是必需的。所以我在父组件和子组件上浏览了 FormBuilder,并在所有表单控件上将 Validators.required
设置为 true。
this._fb.control({
conjunctor: null,
conditions: [[], Validators.required],
groups: [[], Validators.required]
})
(所有控件都是这样)
问题是,表格现在 总是 有效。即使表格实际上无效。是否可以在使用嵌套子组件时检查表单有效性?
如果需要,这里有一些关于这个特定表格的更多信息:
基本上您必须实现 Validator
(不是 Validators
- 复数)接口。它有一个强制方法:
validate(c: AbstractControl) => ValidationErrors;
如果控件有效,方法 validate
应该 return null
,如果控件无效,方法 validate
应该 null
。
还有一件事是您必须以与提供 NG_VALUE_ACCESSOR
.
NG_VALIDATORS
(现在,使用复数)
总结:
@Component({
...
providers: [
...
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => GroupControlComponent),
multi: true
}
]
})
export class GroupControlComponent implements Validator {
...
// Notice that we don't need to use the c parameter passed to the method.
// We are using the `_form` instance property to verify what we need
validate(c: AbstractControl): ValidationErrors {
return this._form.valid ? null : {errors: 'form is invalid'};
}
...
}
您必须对您的 GroupControlComponent
和 ConditionFormComponent
执行此操作。
[更新]:您还需要注意动态创建的控件。在组控件中,让我们看一下具有输入的单个组件:条件控件。而不是:
_addCondition() {
this._conditionsFormArray.push(
this._fb.control({variable: null})
);
}
您应该使用检查 variable
有效性的验证器来初始化控件,因为与 variable
属性关联的基础控件只会在用户与内部输入交互后才进行检查ConditionFormComponent
。所以,你应该这样写:
_addCondition() {
this._conditionsFormArray.push(
this._fb.control({variable: null},
(c: AbstractControl) =>
c.value && c.value.variable ? null : {'required': true}
)
);
}
这是检查 variable
属性有效性的验证函数:
(c: AbstractControl) =>
c.value && c.value.variable ? null : {'required': true}
如果您不这样做,它将覆盖底层 ConditionForm
控件中的验证(表明需要输入)。您可能会遇到一种奇怪的状态,即外部形式(在 GroupControl
中)无效,但内部形式(在 ConditionForm
中)有效。当您在外部表单上验证它时,您基本上甚至可以删除内部表单中的 Validators.required
并仅依赖外部表单验证。