Angular2 - 反应形式属性

Angular2 - Reactive Form Properties

我有一个正在为我的组件生成的响应式表单。大约有 5 个可选 select 输入可供用户选择使用并从中选择标准。

我正在尝试在其中实现一些错误消息,但无法完全弄明白。

<span *ngIf="importForm.invalid && importForm.touched" class="help-block text-danger">Please select one piece of data to filter by.</span>

由于所有字段都是选项,但至少有一个是必需的,我如何才能在显示无效消息之前检查其中一个字段是否已 touched

分量:

/**
 * Render the form in the UI to allow
 *
 * @memberof FilterSearchComponent
 */
renderForm() {
    this.importForm = this.fb.group({
        costCenter: [[]],
        area: [[]],
        silo: [[]],
        department: [[]],
        location: [[]],
        segment: [[]],
        role: [[]]
    },
        {
            validator: (formGroup: FormGroup) => {
                return this.validateFilter(formGroup);
            }
        });
}

/**
 * Checks to see that at least one of the filter
 * options have been filled out prior to searching
 * for employees.
 *
 * @param formGroup
 */
validateFilter(formgroup: FormGroup) {
    if (formgroup.controls["costCenter"].value.length ||
        formgroup.controls["area"].value.length ||
        formgroup.controls["silo"].value.length ||
        formgroup.controls["department"].value.length ||
        formgroup.controls["location"].value.length ||
        formgroup.controls["segment"].value.length ||
        formgroup.controls["role"].value.length
    ) {
        return null;
    } else {
        return { noFilterOptions: true };
    }
}

如果可以的话,我真的不想为 HTML 中的每个控件都执行 || 语句。

有没有其他方法可以查看我表单中的任何输入是否被触摸,而不是单独指定我想查看的输入?

你这里的应该有用:

<span *ngIf="importForm.invalid && importForm.touched" class="help-block text-danger">Please select one piece of data to filter by.</span>

如果表单上的任何控件被触摸,则应设置表单的触摸 属性。我认为它不起作用?怎么没用了?

触摸 -> 用户进入并离开了输入元素。它没有说明用户是否在输入元素中输入了某些内容。

如果您想知道用户是否更新了其中一个输入元素的值,请改用 dirty:

<span *ngIf="importForm.invalid && importForm.dirty" 
      class="help-block text-danger">
   Please select one piece of data to filter by.
</span>

在这里我想删除自定义验证器,因为它现在位于。只要您的表单发生某些事情,它就会被触发,我认为它具有比选择更多的价值。这会经常触发不必要的。

相反,我会收听 click 事件或您选择的类似内容。下面的示例可能会进一步完善(?),但如果您选择按以下方式进行操作,至少您可以使用一些东西。

这里我假设不是对表单中的所有 select 使用数组,而是只想捕获一个值,单个 FormControl 就可以:

this.importForm = this.fb.group({
  optionals: this.fb.group({
    costCenter: [''],
    area: ['']        
  })
});

构建表单后,我喜欢将不同的控件存储到变量中,以避免使用 属性 路径的冗长代码。我会迭代表单组 optionals 中的对象属性,将其存储在数组中,然后我们可以检查是否至少设置了一个值:

this.optionalCtrl = this.importForm.controls.optionals

在模板中,嗯,这里你需要为所有选择单独设置点击事件...

<select formControlName="costCenter" (click)="checkOptionals()">

In checkOptionals 然后将迭代表单组 optionals 中的对象属性并检查至少一个 属性 具有空字符串以外的值。基于此,我们为表单组设置自定义错误,或者清除它。

checkOptionals() {
  for(let key in this.optionalCtrl.controls ) {
    if(this.optionalCtrl.controls[key].value != '') {
      this.optionalCtrl.clearValidators()
      // this.optionalCtrl.updateValueAndValidity()
      break;
    } else {
      this.optionalCtrl.setErrors({"noFilterOptions": true})
    }
  }

} }

您可能需要在设置错误后调用 updateValueAndValidity。然后在模板中,当它为真时,你只显示这个错误:

<div *ngIf="optionalCtrl.hasError('noFilterOptions')">
  choose at least one to filter by
</div>

演示:http://plnkr.co/edit/VbtsYST0KAUqe8BRQlmt?p=preview