Angular2 - 活动表单属性

时间:2017-07-25 18:02:13

标签: angular typescript angular-reactive-forms

我有一个我为我的组件生成的反应形式。用户可以选择使用大约5个可选的选择输入,并从中选择标准。

我正在尝试在此处实现一些错误消息,但无法解决问题。

<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中的每个控件做一个||语句。

如果我的表单中的任何输入被触及而不是指定我想要单独查看的内容,我还能看到其他任何方式吗?

2 个答案:

答案 0 :(得分:1)

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

相反,我会倾听click事件或类似您选择的事件。以下示例可能会进一步细化(?),但如果您选择按以下方式执行此操作,则至少可以使用该示例。

这里我假设您不是在表单中为所有select使用数组,而是只想捕获一个FormControl将执行的值:

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

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

this.optionalCtrl = this.importForm.controls.optionals

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

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

然后在checkOptionals中迭代formgroup 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>

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

答案 1 :(得分:0)

你在这里应该工作:

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

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

触摸 - &gt;用户输入并离开输入元素。它没有说明用户是否在输入元素中输入了内容。

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

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