Angular 2 Final中的最小/最大验证器

Dav*_*vid 36 validation typescript angular2-forms angular

根据thinkgram.io,目前支持的验证器是:

  • 需要
  • 使用MINLENGTH
  • 最长长度
  • 图案

所以,考虑下面的代码(这里是plunkr):

@Component({
  selector: 'my-app',
  template: `

  <form #formRef="ngForm">
    <input type="number" [(ngModel)]="firstValue" name="firstValue" min="0" required/>
    <input type="text" [(ngModel)]="secondValue" maxlength="5" name="secondValue" required/>
    <button type="submit"> Submit </button> 
  </form>

  FORM: {{formRef.form | json }}
`
})
export class AppComponent { 
  firstValue = -22;
  secondValue = "eyy macarena!"; 
}
Run Code Online (Sandbox Code Playgroud)

虽然minlength支持,但min="0"角度验证会忽略它:

在此输入图像描述

在此输入图像描述

因此,要在firstValue ngModel <0时使表单导致错误,我是否需要构建自定义验证器?

Ank*_*ngh 45

要申请min/max validation,number您需要创建一个Custom Validator

Validators类目前只有几个验证器,即

  • 需要
  • requiredTrue
  • 使用MINLENGTH
  • 最长长度
  • 图案
  • nullValidator
  • 撰写
  • composeAsync

验证器: 这是我的号码验证器的简化版本,您可以随意改进它

static number(prms = {}): ValidatorFn {
    return (control: FormControl): {[key: string]: string} => {
      if(isPresent(Validators.required(control))) {
        return null;
      }

      let val: number = control.value;

      if(isNaN(val) || /\D/.test(val.toString())) {

        return {"number": true};
      } else if(!isNaN(prms.min) && !isNaN(prms.max)) {

        return val < prms.min || val > prms.max ? {"number": true} : null;
      } else if(!isNaN(prms.min)) {

        return val < prms.min ? {"number": true} : null;
      } else if(!isNaN(prms.max)) {

        return val > prms.max ? {"number": true} : null;
      } else {

        return null;
      }
    };
  }
Run Code Online (Sandbox Code Playgroud)

用法:

// check for valid number
var numberControl = new FormControl("", [Validators.required, CustomValidators.number()])

// check for valid number and min value  
var numberControl = new FormControl("", CustomValidators.number({min: 0}))

// check for valid number and max value
var numberControl = new FormControl("", CustomValidators.number({max: 20}))

// check for valid number and value range ie: [0-20]
var numberControl = new FormControl("", CustomValidators.number({min: 0, max: 20}))
Run Code Online (Sandbox Code Playgroud)

  • 为什么不使用angular 2只支持输入的内置`min` /`max`属性?这非常不直观 (39认同)
  • Angular 4现在支持最小/最大验证器.https://angular.io/api/forms/Validators (21认同)
  • @Blauhirn不知道,可能那个写验证人的人中途感到无聊:) (16认同)
  • @Olezt,Angular 4现在只支持min/max验证器作为函数而不是指令,这意味着它们在模板驱动的表单中完全没用.这是一个非常奇怪的决定. (5认同)
  • @Senthe最初添加了对模板驱动表单的支持,但这是一个重大变化(因此[回滚](https://github.com/angular/angular/commit/3e685f98c666fcb9f0556ccb65d4b40716ac2985#diff-d60c63de232466b99bc9f5ab2bb39430))因为很多人已经使用`min`和`max`而不是所有人都期待从中验证.有[此请求](https://github.com/angular/angular/issues/16352),但它的范围更大,可能会更慢,所以我添加了[更加量身定制的请求](https:// github.com/angular/angular/issues/23635)刚才. (4认同)

Dav*_*vid 31

我找到了一个实现了很多自定义验证器的库 - ng2-validation - 可以与模板驱动的表单(属性指令)一起使用.例:

<input type="number" [(ngModel)]="someNumber" name="someNumber" #field="ngModel" [range]="[10, 20]"/>
<p *ngIf="someNumber.errors?.range">Must be in range</p>
Run Code Online (Sandbox Code Playgroud)

  • 那肯定对我有用! (13认同)
  • 仅链接的答案 [无用](http://meta.stackexchange.com/q/225370/248731)。 (3认同)

Sad*_*han 18

Angular 现在默认支持最小/最大验证器。

Angular 默认提供以下验证器。在此处添加列表,以便新来者可以轻松了解当前支持的默认验证器是什么,并根据他们的兴趣进一步搜索。

  • 分钟
  • 最大限度
  • 必需的
  • requiredTrue
  • 电子邮件
  • 最小长度
  • 最长长度
  • 图案
  • 空验证器
  • 撰写
  • 撰写异步

您将获得完整的Angular 验证器列表

如何使用最小/最大验证器: 来自 Angular 的文档 -

static min(min: number): ValidatorFn 
static max(max: number): ValidatorFn 
Run Code Online (Sandbox Code Playgroud)

min() / max()是一个静态函数,它接受一个数字参数返回一个验证器函数,如果验证检查失败,则返回一个带有min / max属性的错误映射,否则为 null。

在 formControl 中使用min验证器,(有关更多信息,请单击此处

const control = new FormControl(9, Validators.min(10));
Run Code Online (Sandbox Code Playgroud)

在 formControl 中使用max验证器,(有关更多信息,请单击此处

const control = new FormControl(11, Validators.max(10));
Run Code Online (Sandbox Code Playgroud)

有时我们需要动态添加验证器。setValidators()是救星。你可以像下面这样使用它 -

const control = new FormControl(10);
control.setValidators([Validators.min(9), Validators.max(11)]);
Run Code Online (Sandbox Code Playgroud)


amd*_*amd 11

您可以通过创建实现Validator接口的指令轻松实现自己的验证(模板驱动).

import { Directive, Input, forwardRef } from '@angular/core'
import { NG_VALIDATORS, Validator, AbstractControl, Validators } from '@angular/forms'

@Directive({
  selector: '[min]',
  providers: [{ provide: NG_VALIDATORS, useExisting: MinDirective, multi: true }]
})
export class MinDirective implements Validator {

  @Input() min: number;

  validate(control: AbstractControl): { [key: string]: any } {

    return Validators.min(this.min)(control)

    // or you can write your own validation e.g.
    // return control.value < this.min ? { min:{ invalid: true, actual: control.value }} : null



  }

}
Run Code Online (Sandbox Code Playgroud)

  • 对于模板驱动的表单,这是最好的解决方案。在这里创建了一个 stackblitz:https://stackblitz.com/edit/angular-min-max-validation (3认同)

shl*_*Lan 10

我现在正在寻找同样的东西,用来解决它.

我的代码:

this.formBuilder.group({
  'feild': [value,  [Validators.required, Validators.min(1)]]
});
Run Code Online (Sandbox Code Playgroud)


小智 9

据我所知,现在是否实现,请查看https://github.com/angular/angular/blob/master/packages/forms/src/validators.ts

这是实现您所需要的部分:

 export class Validators {
  /**
   * Validator that requires controls to have a value greater than a number.
   */
  static min(min: number): ValidatorFn {
    return (control: AbstractControl): ValidationErrors | null => {
      if (isEmptyInputValue(control.value) || isEmptyInputValue(min)) {
        return null;  // don't validate empty values to allow optional controls
      }
      const value = parseFloat(control.value);
      // Controls with NaN values after parsing should be treated as not having a
      // minimum, per the HTML forms spec: https://www.w3.org/TR/html5/forms.html#attr-input-min
      return !isNaN(value) && value < min ? {'min': {'min': min, 'actual': control.value}} : null;
    };
  }

  /**
   * Validator that requires controls to have a value less than a number.
   */
  static max(max: number): ValidatorFn {
    return (control: AbstractControl): ValidationErrors | null => {
      if (isEmptyInputValue(control.value) || isEmptyInputValue(max)) {
        return null;  // don't validate empty values to allow optional controls
      }
      const value = parseFloat(control.value);
      // Controls with NaN values after parsing should be treated as not having a
      // maximum, per the HTML forms spec: https://www.w3.org/TR/html5/forms.html#attr-input-max
      return !isNaN(value) && value > max ? {'max': {'max': max, 'actual': control.value}} : null;
    };
  }
Run Code Online (Sandbox Code Playgroud)

  • 验证**逻辑**存在于Angular中,但它们没有将其作为指令公开.因此,任何做模板驱动表单的人仍然需要编写自己的指令(如@ amd的回答所示),或使用库. (4认同)

tre*_*eat 5

  1. 切换到使用反应形式而不是模板形式(它们只是更好),否则第5步将略有不同.
  2. 创建服务NumberValidatorsService并添加验证器函数:

    import { Injectable } from '@angular/core';
    import { FormControl,  ValidatorFn } from '@angular/forms';
    
    @Injectable()
    export class NumberValidatorsService {
    
     constructor() { }
    
      static max(max: number): ValidatorFn {
    return (control: FormControl): { [key: string]: boolean } | null => {
    
      let val: number = control.value;
    
      if (control.pristine || control.pristine) {
        return null;
      }
      if (val <= max) {
        return null;
      }
      return { 'max': true };
      }
    }
    
     static min(min: number): ValidatorFn {
    return (control: FormControl): { [key: string]: boolean } | null => {
    
      let val: number = control.value;
    
      if (control.pristine || control.pristine) {
        return null;
      }
      if (val >= min) {
        return null;
      }
      return { 'min': true };
      }
    }
    
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 将服务导入模块.

  4. 在组件中添加包含语句的语句:

        import { NumberValidatorsService } from "app/common/number-validators.service";
    
    Run Code Online (Sandbox Code Playgroud)
  5. 将验证器添加到表单构建器:

        this.myForm = this.fb.group({
          numberInputName: [0, [Validators.required, NumberValidatorsService.max(100), NumberValidatorsService.min(0)]],
        });
    
    Run Code Online (Sandbox Code Playgroud)
  6. 在模板中,您可以按如下方式显示错误:

     <span *ngIf="myForm.get('numberInputName').errors.max">
             numberInputName cannot be more than 100. 
      </span>
    
    Run Code Online (Sandbox Code Playgroud)


Eug*_*hov 5

显然,Angular在某个时候具有模板驱动形式的max / min指令,但必须在v4.2.0中将其删除。您可以在此处阅读有关导致删除的回归的信息:https : //github.com/angular/angular/issues/17491

目前,我所知道的唯一可行的解​​决方案是使用@amd建议的自定义指令。这是在Bootstrap 4中使用它的方法。

min-validator.directive.ts

import { Directive, Input } from '@angular/core'
import { NG_VALIDATORS, Validator, AbstractControl, Validators } from '@angular/forms'

@Directive({
  selector: '[min]',
  providers: [{ provide: NG_VALIDATORS, useExisting: MinDirective, multi: true }]
})
export class MinDirective implements Validator {

  @Input() min: number;

  validate(control: AbstractControl): { [key: string]: any } {    
    return Validators.min(this.min)(control)    
  }
}
Run Code Online (Sandbox Code Playgroud)

在您的模板中:

<input type="number" [min]="minAge" #age="ngModel" [(ngModel)]="person.age" class="form-control" [ngClass]="{'is-invalid':age.invalid}">
<div *ngIf="age.invalid && (age.dirty || age.touched)" class="invalid-feedback">You need to be older than {{minAge}} to participate</div>
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!