构建 Angular2 表单 - 如何包含验证的条件表单字段
Structuring Angular2 Forms - How to include conditional form fields that validate
背景
Jecelyn Yeen excellent article 关于如何在 Angular2 中组织嵌套表单。
在她的示例中,她使用一个数组来显示多个地址表单子组件,以便用户可以无休止地单击 "Add Address" 并且表单仍然会正确验证。我想做类似的事情,但不是有一个子表单数组,而是根据下拉列表的值显示不同的子表单。
我尝试用与她类似的方式构建我的代码,除了我没有返回表单构建器数组,而是为我想显示的每个子表单使用了一个表单组。选择下拉选项时,我删除了不应显示的表单组,并重新创建应该显示的表单组。我遇到的问题是,当以这种方式构建时,父表单不会在子表单中获取更改。
代码
ts:
public showNameForm: boolean = false;
public showAddressForm: boolean = false;
public showPhoneNumberForm: boolean = false;
constructor (fb: FormBuilder) {
this.myForm = fb.group({
nameInfo: this.getNameForm(),
addressInfo: this.getAddressForm(),
phoneNumberInfo: this.getPhoneNumberForm()
});
}
getNameForm () {
return this.fb.group({
name: ["", Validators.required]
});
}
getAddressForm () {
return this.fb.group({
address1: ["", Validators.required],
address2: ["", Validators.required],
city: ["", Validators.required],
state: ["", Validators.required],
zipcode: ["", Validators.required]
});
}
getPhoneNumberForm () {
return this.fb.group({
phone: ["", Validators.required]
});
}
handleDropdownSelect (value) {
if(value === 1) {
this.showNameForm = true;
this.myForm.controls['nameInfo'] = this.getNameForm();
delete this.myForm.controls['addressInfo'];
delete this.myForm.controls['phoneNumberInfo'];
}
// Similar for other cases, e.g. if value is 2, only show addressInfo
}
html:
<form [formGroup]="myForm">
<div [formGroupName]="'nameInfo'" *ngIf="showNameForm">
<input type="text" formControlName="name" />
</div>
<!-- Similar for other fields -->
<!-- ... -->
<button [ngClass]="{disabled: !myForm.valid}">Submit</button>
</form>
这样做,提交按钮总是无效,即使在我键入所有必需的文本之后也是如此。使用 Chrome 调试器检查表单对象,我发现 myForm.value
等于
{
nameInfo: {
name: ""
}
}
换句话说,我在子表单组中输入的文本永远不会被父表单提取。但是我可以看到 myForm.controls.nameInfo
确实有一个包含正确信息的值,当其他人被选中时也是如此。所有这些属性的 valid
属性 为 true
。然而,除非我手动调用 myForm.updateValueAndValidity()
,否则父表单不会获取这些更改。这并不理想,因为我希望表单一生效就显示为有效,而不必添加我自己的事件侦听器来实现它。
根据评论,问题在于隐藏控件并且它们仍在计算验证。
如果您要隐藏和显示 select FormGroups
并且不希望它们计入验证或 form.value
属性 那么您可以调用 disable()
在单个控件上或在包含 FormGroup
:
上
this.myForm.addressInfo.disable(); // disables the entire addressInfo group
// which removes it from validation, thus preventing false flags.
背景
Jecelyn Yeen excellent article 关于如何在 Angular2 中组织嵌套表单。
在她的示例中,她使用一个数组来显示多个地址表单子组件,以便用户可以无休止地单击 "Add Address" 并且表单仍然会正确验证。我想做类似的事情,但不是有一个子表单数组,而是根据下拉列表的值显示不同的子表单。
我尝试用与她类似的方式构建我的代码,除了我没有返回表单构建器数组,而是为我想显示的每个子表单使用了一个表单组。选择下拉选项时,我删除了不应显示的表单组,并重新创建应该显示的表单组。我遇到的问题是,当以这种方式构建时,父表单不会在子表单中获取更改。
代码
ts:
public showNameForm: boolean = false;
public showAddressForm: boolean = false;
public showPhoneNumberForm: boolean = false;
constructor (fb: FormBuilder) {
this.myForm = fb.group({
nameInfo: this.getNameForm(),
addressInfo: this.getAddressForm(),
phoneNumberInfo: this.getPhoneNumberForm()
});
}
getNameForm () {
return this.fb.group({
name: ["", Validators.required]
});
}
getAddressForm () {
return this.fb.group({
address1: ["", Validators.required],
address2: ["", Validators.required],
city: ["", Validators.required],
state: ["", Validators.required],
zipcode: ["", Validators.required]
});
}
getPhoneNumberForm () {
return this.fb.group({
phone: ["", Validators.required]
});
}
handleDropdownSelect (value) {
if(value === 1) {
this.showNameForm = true;
this.myForm.controls['nameInfo'] = this.getNameForm();
delete this.myForm.controls['addressInfo'];
delete this.myForm.controls['phoneNumberInfo'];
}
// Similar for other cases, e.g. if value is 2, only show addressInfo
}
html:
<form [formGroup]="myForm">
<div [formGroupName]="'nameInfo'" *ngIf="showNameForm">
<input type="text" formControlName="name" />
</div>
<!-- Similar for other fields -->
<!-- ... -->
<button [ngClass]="{disabled: !myForm.valid}">Submit</button>
</form>
这样做,提交按钮总是无效,即使在我键入所有必需的文本之后也是如此。使用 Chrome 调试器检查表单对象,我发现 myForm.value
等于
{
nameInfo: {
name: ""
}
}
换句话说,我在子表单组中输入的文本永远不会被父表单提取。但是我可以看到 myForm.controls.nameInfo
确实有一个包含正确信息的值,当其他人被选中时也是如此。所有这些属性的 valid
属性 为 true
。然而,除非我手动调用 myForm.updateValueAndValidity()
,否则父表单不会获取这些更改。这并不理想,因为我希望表单一生效就显示为有效,而不必添加我自己的事件侦听器来实现它。
根据评论,问题在于隐藏控件并且它们仍在计算验证。
如果您要隐藏和显示 select FormGroups
并且不希望它们计入验证或 form.value
属性 那么您可以调用 disable()
在单个控件上或在包含 FormGroup
:
this.myForm.addressInfo.disable(); // disables the entire addressInfo group
// which removes it from validation, thus preventing false flags.