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

Posted

技术标签:

【中文标题】Angular 2 Final 中的最小/最大验证器【英文标题】:Min / Max Validator in Angular 2 Final 【发布时间】:2017-02-12 08:35:04 【问题描述】:

根据thoughtgram.io,目前支持的验证器有:

需要 最小长度 最大长度 模式

因此,考虑以下代码 (plunkr here):

@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!"; 

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

那么,要让表单在 firstValue ngModel

【问题讨论】:

FirstValue &lt; 0&lt;input ngModel="firstValue" min="0"。表单状态:VALID。我是否真的需要构建一个自定义验证器来确保表单状态:INVALID 当模型超出min / max 值的范围时,或者是否有 NG2 本身支持的东西? 是的,你需要。在此处查看源代码:github.com/angular/angular/blob/master/modules/%40angular/forms/… 只有 thinkram 文章中提到的这 4 个验证器才支持 OOTB。 【参考方案1】:

要在number 上应用min/max validation,您需要创建一个Custom Validator

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

必填 需要True 最小长度 最大长度 模式 nullValidator 撰写 composeAsync

验证器: 这是我的号码验证器的低调版本,您可以根据需要改进它

static number(prms = ): ValidatorFn 
    return (control: FormControl): [key: string]: any => 
      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;
      
    ;
  

用法:

// 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))

【讨论】:

为什么 Angular 2 不支持内置的 min/max 输入属性?这是非常不直观的 @Blauhirn 不知道,可能编写验证器的人在中途感到无聊:) Angular 4 现在支持最小/最大验证器。 angular.io/api/forms/Validators @Olezt,Angular 4 现在只支持最小/最大验证器作为函数而不是指令,这意味着它们在模板驱动的表单中完全没用。这是一个非常奇怪的决定。 @Senthe 最初添加了对模板驱动表单的支持,但这是一个重大更改(因此 rolled back),因为许多人已经在使用 minmax,但并非所有人都在使用期待它的验证。有this request,但它的范围更大,可能会更慢,所以我刚刚添加了a more tailored request。【参考方案2】:

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

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

【讨论】:

仅链接的答案是not useful。 嗯,这对我很有用! 当心:我的应用程序的 AOT 版本似乎存在问题。 @KumarSaurabh 同意,最好包含答案的基本部分 - 但您的评论将此标记为“建议删除?” 这个链接很有用。但是,从技术上讲,它是一个仅限链接的答案,因此我进行了编辑以包含一个小解释和一个示例。【参考方案3】:

您可以通过创建实现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



  


【讨论】:

如果你解释像上面***.com/a/44722596/3898339的答案会更有帮助 正是我在编写模板驱动表单时所需要的! 使用模板驱动的表单,这是最好的解决方案。在这里创建了一个堆栈闪电战:stackblitz.com/edit/angular-min-max-validation 注:你必须使用括号,如[min]="0" 而不是min="0",因为指令需要一个数字,而不是字符串。【参考方案4】:

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

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

分钟 最大 必填 需要True 电子邮件 最小长度 最大长度 模式 nullValidator 撰写 composeAsync

您将获得完整列表Angular validators

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

static min(min: number): ValidatorFn 
static max(max: number): ValidatorFn 

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

在 formControl 中使用 min 验证器,(更多信息,click here)

const control = new FormControl(9, Validators.min(10));

在 formControl 中使用 ma​​x 验证器,(更多信息,click here)

const control = new FormControl(11, Validators.max(10));

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

const control = new FormControl(10);
control.setValidators([Validators.min(9), Validators.max(11)]);

【讨论】:

【参考方案5】:

我现在也在找同样的东西,用this解决了。

我的代码:

this.formBuilder.group(
  'feild': [value,  [Validators.required, Validators.min(1)]]
);

【讨论】:

需要注意的是,Validators 上的 min() 和 max() 函数只存在于最新 Angular 8 的 angular/forms 上。 min() 和 max() 作为函数而不是指令存在 这是针对反应式表单的解决方案,而不是模板驱动的表单。【参考方案6】:

据我所知,现在有没有实现,查看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;
    ;
  

【讨论】:

验证 logic 存在于 Angular 中,但他们没有将其作为指令公开。所以任何做模板驱动表单的人仍然需要编写自己的指令(如@amd 的答案所示),或者使用库。【参考方案7】:

显然,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)    
  

在你的模板中:

<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>

希望这会有所帮助!

【讨论】:

【参考方案8】:
    改用响应式表单而不是模板表单(它们更好),否则第 5 步会略有不同。

    创建一个服务 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 ;
      
    
    
    
    

    将服务导入模块。

    在要使用的组件中添加包含语句:

        import  NumberValidatorsService  from "app/common/number-validators.service";
    

    将验证器添加到表单构建器:

        this.myForm = this.fb.group(
          numberInputName: [0, [Validators.required, NumberValidatorsService.max(100), NumberValidatorsService.min(0)]],
        );
    

    在模板中,可以如下显示错误:

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

【讨论】:

在您需要连接disabled 之前,它们会更好,此时您会发现要使其正常工作非常麻烦。您最终不得不创建各种复杂的订阅、设置访问器和更改检测器,只是为了动态禁用您的表单。可怕的是,Angular 决定放弃在反应式表单控件中为 disable 初始化提供函数的能力。【参考方案9】:

我发现这是一个解决方案。如下创建一个自定义验证器

minMax(control: FormControl) 
      return parseInt(control.value) > 0 && parseInt(control.value) <=5 ? null : 
        minMax: true
      
  

在构造函数下包含以下代码

this.customForm= _builder.group(
                  'number': [null, Validators.compose([Validators.required, this.minMax])],
                );

其中 customForm 是 FormGroup 而 _builder 是 FormBuilder。

【讨论】:

【参考方案10】:

Angular 6 支持 minma​​x 验证器:https://angular.io/api/forms/Validators

您可以将它们用于静态和动态值。

静态:

<input min="0" max="5">

动态:

<input [min]="someMinValue" [max]="someMaxValue">

【讨论】:

@sumitkanoje 在 Angular 5 中,以下内容以模板驱动形式为我工作:this.templateItem1 = new FormControl('', [ Validators.required, Validators.pattern('[0-9]+'), Validators.min(1), Validators.max(10) ]); 对于必需的输入字段,仅允许数字,并且必须在 [1-10 ]。在 HTML 中,元素是:&lt;input type="text" class="form-control" id="item1" formControlName="templateItem1"&gt;(并且存在于 form-groupform 元素中),然后您可以使用 form-control-feedbacktemplateItem1.errors .dirty .touched 来获取验证消息。 它不是模板驱动的表单 来自有关 min 和 max 的 Angular 文档:“验证器仅作为函数存在,而不作为指令存在。”最小值最大值仅适用于反应形式。【参考方案11】:

Angular 有 min 和 max 验证器,但仅适用于响应式表单。正如它在文档中所说:“验证器仅作为函数存在,而不是作为指令存在。”

为了能够在模板驱动的表单中使用这些验证器,您需要创建自定义指令。在我的实现中,我使用@HostBinding 来应用 HTML min/max-attributes。我的selectors 也非常具体,以防止在自定义表单控件上运行验证,这些控件使用ControlValueAccessor 实现minmax 输入(例如MatDatePickerInput)

最小验证器:

import  Directive, HostBinding, Input  from '@angular/core';
import  AbstractControl, NG_VALIDATORS, ValidationErrors, Validator, Validators  from '@angular/forms';

@Directive(
  selector: 'input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]',
  providers: [ provide: NG_VALIDATORS, useExisting: MinValidatorDirective, multi: true ]
)
export class MinValidatorDirective implements Validator 
  @HostBinding('attr.min') @Input() min: number;

  constructor()  

  validate(control: AbstractControl): ValidationErrors | null 
    const validator = Validators.min(this.min);
    return validator(control);
  

最大验证器:

import  Directive, HostBinding, Input  from '@angular/core';
import  AbstractControl, NG_VALIDATORS, ValidationErrors, Validator, Validators  from '@angular/forms';

@Directive(
  selector: 'input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]',
  providers: [ provide: NG_VALIDATORS, useExisting: MaxValidatorDirective, multi: true ]
)
export class MaxValidatorDirective implements Validator 
  @HostBinding('attr.max') @Input() max: number;

  constructor()  

  validate(control: AbstractControl): ValidationErrors | null 
    const validator = Validators.max(this.max);
    return validator(control);
  


【讨论】:

【参考方案12】:

Angualr 本身提供最小和最大数字验证功能。

示例 - 我们有一个年龄范围之类的字段,然后查看验证的使用。

  age_range : ['',  Validators.min(1), Validators.max(18)]]

年龄总是在 1 到 18 岁之间。

【讨论】:

【参考方案13】:

在最新的 Angular 版本中,已经添加了最小值和最大值。链接在这里: https://angular.io/api/forms/Validators#max

这就是我在项目中使用 Max 验证器的方式:

<mat-form-field class="globalInput">
          <input (change)="CalculateAmount()" matInput placeholder="Quantity" name="productQuantity" type="number" [formControl]="quantityFormControl">
        </mat-form-field>
        <mat-error *ngIf="quantityFormControl.hasError('max')">
          Only <strong>productQuantity</strong> available!
        </mat-error>

初始化表单控件并在组件中添加验证器:

  quantityFormControl = new FormControl('', Validators.max(15));

您还可以像这样在事件上动态设置验证器:

  quantityFormControl = new FormControl();

OnProductSelected()
    this.quantityFormControl.setValidators(Validators.max(this.someVariable));
  

希望对你有帮助。

【讨论】:

【参考方案14】:

在我的模板驱动表单(Angular 6)中,我有以下解决方法:

 <div class='col-sm-2 form-group'>
            <label for='amount'>Amount</label>
            <input type='number' 
                   id='amount' 
                   name='amount' 
                   required 
                   [ngModel] = 1
                   [pattern] = "'^[1-9][0-9]*$'"
                   class='form-control' 
                   #amountInput='ngModel'/>
            <span class='text-danger' *ngIf="amountInput.touched && amountInput.invalid">
              <p *ngIf="amountInput.errors?.required">This field is <b>required</b>!</p>
              <p *ngIf="amountInput.errors?.pattern">This minimum amount is <b>1</b>!</p>
            </span>
        </div>

上面的许多示例都使用了指令和自定义类,它们在更复杂的形式中可以更好地扩展,但是如果您正在寻找一个简单的数字最小值,请使用 pattern 作为指令并仅对正数施加正则表达式限制.

【讨论】:

【参考方案15】:

找到用于最小值验证的自定义验证器。我们指令的选择器名称是 customMin。

custom-min-validator.directive.ts

import  Directive, Input  from '@angular/core';
import  NG_VALIDATORS, Validator, FormControl  from '@angular/forms';

@Directive(
  selector: '[customMin][formControlName],[customMin][formControl],[customMin][ngModel]',
  providers: [provide: NG_VALIDATORS, useExisting: CustomMinDirective, multi: true]
)
export class CustomMinDirective implements Validator 
  @Input()
  customMin: number;

  validate(c: FormControl): [key: string]: any 
      let v = c.value;
      return ( v < this.customMin)? "customMin": true : null;
  
 

找到最大数量验证的自定义验证器。我们指令的选择器名称是 customMax。

custom-max-validator.directive.ts

import  Directive, Input  from '@angular/core';
import  NG_VALIDATORS, Validator, FormControl  from '@angular/forms';

@Directive(
  selector: '[customMax][formControlName],[customMax][formControl],[customMax][ngModel]',
  providers: [provide: NG_VALIDATORS, useExisting: CustomMaxDirective, multi: true]
)
export class CustomMaxDirective implements Validator 
  @Input()
  customMax: number;

  validate(c: FormControl): [key: string]: any 
      let v = c.value;
      return ( v > this.customMax)? "customMax": true : null;
  
 

我们可以将 customMaxformControlNameformControlngModel 属性一起使用。

在模板驱动表单中使用自定义最小值和最大值验证器

我们将以模板驱动的形式使用自定义的最小和最大验证器。对于最小数量验证,我们有 customMin 属性,对于最大数量验证,我们有 customMax 属性。现在找到验证码sn-p。

<input name="num1" [ngModel]="user.num1" customMin="15" #numberOne="ngModel">
<input name="num2" [ngModel]="user.num2" customMax="50"  #numberTwo="ngModel"> 

我们可以显示验证错误消息如下。

<div *ngIf="numberOne.errors?.customMin"> 
     Minimum required number is 15.
</div>  

<div *ngIf="numberTwo.errors?.customMax"> 
     Maximum number can be 50.
</div> 

要分配最小和最大数量,我们还可以使用财产投标。假设我们有以下组件属性。

minNum = 15;
maxNum = 50; 

现在对 customMin 和 customMax 使用属性绑定,如下所示。

<input name="num1" [ngModel]="user.num1" [customMin]="minNum" #numberOne="ngModel">
<input name="num2" [ngModel]="user.num2" [customMax]="maxNum"  #numberTwo="ngModel"> 

【讨论】:

这对我有用,但你应该编辑指令以转换为数字,因为它正在与 "v > this.customMax" 到 "v > +this.customMax" 中的字符串进行比较,因为它不起作用在角度 7 这可能是因为输入类型可能等于文本而不是数字。因此,您可以转换为数字或将类型更改为数字【参考方案16】:

我的严格编译器版本

import  Directive, Input  from '@angular/core';
import  AbstractControl, NG_VALIDATORS, ValidationErrors, Validator  from '@angular/forms';

@Directive(
  selector: '[appMinValidator]',
  providers: [ provide: NG_VALIDATORS, useExisting: MinValidatorDirective, multi: true ]
)
export class MinValidatorDirective implements Validator 

  @Input()
  appMinValidator!: number;

  validate(control: AbstractControl): ValidationErrors | null 
    return (control.value as number < this.appMinValidator) ?  appMinValidator: true  : null;
  


【讨论】:

【参考方案17】:

使用

Validators.min(5)

它可以在创建 formGroup 变量以及其他验证器时使用,如

dueAmount:['', [Validators.required, Validators.pattern(/^[+]?([0-9]+(?:[\.][0-9]*)?|\.[0-9]+)$/), Validators.min(5)]]

不确定它是否在 Angular 2 中,但在 Angular 5

中可用

【讨论】:

【参考方案18】:

我在 AMD 的最佳答案中添加了 max 验证。

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

/*
 * This is a wrapper for [min] and [max], used to work with template driven forms
 */

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

  @Input() min: number;

  validate(control: AbstractControl):  [key: string]: any  
    return Validators.min(this.min)(control)
  


@Directive(
  selector: '[max]',
  providers: [ provide: NG_VALIDATORS, useExisting: MaxNumberValidator, multi: true ]
)
export class MaxNumberValidator implements Validator 

  @Input() max: number;

  validate(control: AbstractControl):  [key: string]: any  
    return Validators.max(this.max)(control)
  

【讨论】:

【参考方案19】:

这个问题已经回答了。我想从@amd 扩展答案。有时您可能需要一个默认值。

例如,要针对特定​​值进行验证,我想提供如下-

<input integerMinValue="20" >

但是 32 位有符号整数的最小值是 -2147483648。为了验证这个值,我不想提供它。我想写如下-

<input integerMinValue >

要实现这一点,您可以按如下方式编写指令

import Directive, Input from '@angular/core';
import AbstractControl, NG_VALIDATORS, ValidationErrors, Validator, Validators from '@angular/forms';

@Directive(
    selector: '[integerMinValue]',
    providers: [provide: NG_VALIDATORS, useExisting: IntegerMinValidatorDirective, multi: true]
)
export class IntegerMinValidatorDirective implements Validator 

    private minValue = -2147483648;

    @Input('integerMinValue') set min(value: number) 
        if (value) 
            this.minValue = +value;
        
    

    validate(control: AbstractControl): ValidationErrors | null 
        return Validators.min(this.minValue)(control);
    


【讨论】:

【参考方案20】:

在您的代码中,您使用的是min 而不是minlength。另请注意,这不会验证数字是否 > 0 但其长度。

【讨论】:

问题是关于 NG2 验证如何支持 minlength 而 min 不支持,如果这是有意的,开箱即用的东西 - 或者只是我缺少的一些 NG 知识。我知道 min 和 minlength 之间的区别:P

以上是关于Angular 2 Final 中的最小/最大验证器的主要内容,如果未能解决你的问题,请参考以下文章

猫鼬中的最小和最大数量验证

使用Angular 7中的最大化/最小化图标调整引导模式对话框的大小

Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) E - Goods transportation 最大流转最小割转dp(示例

Angular 2 Ionic 2 - 如何将最大或最小日期设置为今天以进行日期输入?

bzoj 3721 Final Bazarek

在 Array Angular 和 Typescript 中查找最小和最大元素