构造Angular2表单 - 如何包含验证

时间:2016-11-30 21:23:51

标签: angular angular2-forms

上下文

Jecelyn Yeen对如何在Angular2中组织嵌套表单有一个excellent article

在她的例子中,她使用一个数组来显示多个地址表单子组件,这样用户就可以无休止地点击"添加地址"并且表单仍将正确验证。我想做类似的事情,但不是有一个子表单数组,而是根据下拉列表的值显示不同的子表单。

我尝试构造我的代码与她的代码类似,除了不返回表单构建器数组,我为每个要显示的子表单使用表单组。选择下拉选项后,我会删除不应显示的表单组,并重新创建应该显示的表单组。我遇到的问题是,当以这种方式构建时,父表单不会在子表单中获取更改。

守则

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(),否则父表单不会接收这些更改。这并不理想,因为我希望表单一旦有效就显示为有效,而不必添加我自己的事件监听器来实现它。

1 个答案:

答案 0 :(得分:1)

根据评论,问题是隐藏控件,它们仍然计入验证。

如果您隐藏并显示选择FormGroups并且不希望它们计入验证或form.value属性,那么您可以在单个控件上调用disable()或在包含FormGroup

this.myForm.addressInfo.disable(); // disables the entire addressInfo group
// which removes it from validation, thus preventing false flags.