【问题标题】:Angular2 - Reactive Forms ValidationAngular2 - 反应式表单验证
【发布时间】:2017-07-28 01:37:05
【问题描述】:

我正在为我的反应形式的一组输入创建一个验证器。

this.transitionForm = this.fb.group({
  effectiveStartDate: [this.utils.dateToISO(startDate), Validators.compose([Validators.required, this.validateDates])],
  effectiveEndDate: [(endDate ? endDate : ''), Validators.compose([Validators.required, this.validateDates])],
});

/**
 * Checks to make sure the start and end date selected
 * are in an acceptable format.
 *
 * @param formGroup
 */
validateDates(formgroup: FormGroup) {

    const start = formgroup.controls["effectiveStartDate"].value;
    const end = formgroup.controls["effectiveEndDate"].value;

    /**
     *   Validation Logic
     * - End date cannot come before start date
     * - Start date cannot come after end date
     * - Start date cannot be empty
     * - End Date cannot be empty
     */
    if ((end < start) || (start > end) || !start || !end) {
        return { invalidDates: true };
    } else {
        return null;
    }
}

HTML:

<div *ngIf="!transitionForm.controls['effectiveEndDate'].valid">
 <p *ngIf="transitionForm.controls['effectiveEndDate'].errors.invalidDates">
  Invalid End Dates
 </p>
</div>

由于某种原因,例如,当我将结束日期留空时,我的错误没有出现。我觉得也许我错误地调用了验证器? Compose 是我能找到的将多个验证器链接在一起的唯一方法,但我不确定是否需要传递任何东西?

更新:

这是我现有的完整表单,从各个控件中删除了验证器。它还表明我目前为这个表单设置了一个验证器,可能是不正确的。

如何包含多个?

this.transitionForm = this.fb.group({
    changeType: ['', Validators.required],
    effectiveStartDate: [this.utils.dateToISO(startDate), Validators.required],
    effectiveEndDate: [(endDate ? endDate : ''), Validators.required],

},
    {
        // Validate to make sure we selected at least one transition field
        validator: (formGroup: FormGroup) => {
            return this.validateFilter(formGroup);
        }
    });

【问题讨论】:

  • 如果 startDate 输入 endDate 是强制性的吗?需要这种类型的验证吗?

标签: angular typescript angular-reactive-forms


【解决方案1】:

我同意 Deborah 的观点,即为您的日期设置一个嵌套表单组。 为什么? 性能方面,特别是如果您的表单中有许多(其他)字段,设置它验证表单中的任何字段更改时,它会被多次触发,所以一定要做像 Deborah 这样的事情介绍:

...
dates: this.fb.group({
  effectiveStartDate: [this.utils.dateToISO(startDate), Validators.required],
  effectiveEndDate: [(endDate ? endDate : ''), Validators.required],
},{validator: this.validateDates})
...

只有在dates 组发生更改时才会触发它。

至于您的自定义验证器,您无需检查日期是否存在,因为您已经拥有Validators.required,因此将您的自定义验证器更改为:

validateDates(dates: FormGroup) { // here is the 'dates' formgroup (only)
  const start = dates.controls["effectiveStartDate"].value;
  const end = dates.controls["effectiveEndDate"].value;

  if ((end < start) || (start > end)) {
     return { invalidDates: true };
  } else {
     return null;
  }
}

关于在模板中显示错误消息的问题。它不适用于errors.invalidDates,您可以使用hasError。在这种情况下,您可以非常巧妙地显示错误:

<p *ngIf="transitionForm.hasError('invalidDates', 'dates')">

【讨论】:

    【解决方案2】:

    为控制组构建验证器时,您需要将验证器添加到组中,而不是添加到各个控件中。

        this.customerForm = this.fb.group({
            firstName: ['', [Validators.required, Validators.minLength(3)]],
            lastName: ['', [Validators.required, Validators.maxLength(50)]],
            emailGroup: this.fb.group({
                email: ['', [Validators.required, Validators.pattern('[a-z0-9._%+-]+@[a-z0-9.-]+')]],
                confirmEmail: ['', Validators.required],
            }, {validator: emailMatcher}),
            phone: '',
            notification: 'email',
            rating: ['', ratingRange(1, 5)],
            sendCatalog: true,
            addresses: this.fb.array([this.buildAddress()])
        });
    

    另外,你不再需要 compose ... 那是 Angular 的早期版本。

    【讨论】:

    • 我用我已经有一个验证器的完整表格更新了我的原始帖子。它看起来也和你的完全不同。我怎么能同时包含两者?
    • 我不确定我是否理解?要包含两个验证器,请将它们包含在一个数组中。我在上面的代码中有一个示例,其中需要电子邮件并且必须匹配模式。
    • 我更新了我的示例以显示我的整个表单。请注意,这两个字段(在我的示例中为电子邮件)位于它们自己的表单组中。该组具有与之关联的跨字段验证。
    猜你喜欢
    • 2017-12-30
    • 2017-11-22
    • 2017-11-02
    • 2019-05-04
    • 2018-07-08
    • 2020-05-15
    • 2020-12-05
    相关资源
    最近更新 更多