【问题标题】:Structuring Angular2 Forms - How to include conditional form fields that validate构建 Angular2 表单 - 如何包含验证的条件表单字段
【发布时间】:2017-04-15 08:56:09
【问题描述】:

背景

Jecelyn Yeen 有一个excellent article,关于如何在 Angular2 中组织嵌套表单。

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

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

守则

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

【问题讨论】:

  • 你为什么绑定[ngClass]而不是按钮上的[disabled]属性?其中之一实际上控制按钮是否将被禁用。另一种是根据表单有效性将 css 类应用于按钮。 plnkr.co/edit/usLejtwhMZGjyxS6InCb?p=preview
  • 你是对的!我道歉。我在本地看到了这一点,因为我在选择下拉列表时更新了应该显示的表单。我正在删除其他表单组件,然后执行myForm.addressInfo = this.getAddressForm(),这破坏了模板。所以我想真正的问题是如何有选择地显示子表单并让父表单正确验证(当未显示的表单的必填字段为空时,似乎返回无效,当他们'不显示)。
  • IIRC 禁用控件不计入验证。通过disable() 在您未显示的组上以编程方式禁用应该可以解决问题。如果您想更新您的问题并且如果可行,我会在明天回来并将其作为答案。
  • 如果我记错了,我会去研究一下。
  • 谢谢!那确实奏效了。请随意添加正确答案,我会接受的。

标签: angular angular2-forms


【解决方案1】:

根据 cmets,问题在于隐藏控件并且它们仍然计入验证。

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

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

【讨论】:

    猜你喜欢
    • 2016-07-23
    • 2016-10-26
    • 1970-01-01
    • 1970-01-01
    • 2020-06-12
    • 2021-07-10
    • 1970-01-01
    • 2015-06-24
    • 2017-04-21
    相关资源
    最近更新 更多