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

Min / Max Validator in Angular 2 Final

根据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" 被 angular 验证忽略:

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

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

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

Validators class 目前只有几个验证者,即

  • 需要
  • requiredTrue
  • 最小长度
  • 最大长度
  • 模式
  • nullValidator
  • 撰写
  • composeAsync

Validator: 这是我的号码验证器的精简版,你可以根据自己的喜好改进

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

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

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

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

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。

据我所知,现在实现了吗,查看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;
    };
  }
  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 };
      }
    }
    
    }
    
  3. 将服务导入模块。

  4. 在要使用的组件中添加 includes 语句:

        import { NumberValidatorsService } from "app/common/number-validators.service";
    
  5. 向表单生成器添加验证器:

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

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

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



  }

}

Angular 6 支持 min & max 验证器:https://angular.io/api/forms/Validators

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

静态:

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

动态:

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

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

希望对您有所帮助!

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

我的代码:

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

使用

Validators.min(5)

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

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

不确定它是否在 Angular 2 中,但在 Angular 5[= 中可用13=]

在最新的 Angular 版本中,已经添加了 min 和 max。这是 link: 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));
  }

希望对您有所帮助。

Angular now supports min/max validators by default.

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

  • 分钟
  • 最大
  • 需要
  • requiredTrue
  • 电子邮件
  • 最小长度
  • 最大长度
  • 模式
  • nullValidator
  • 撰写
  • composeAsync

您将获得完整列表Angular validators

如何使用min/max验证器: 来自 Angular -

的文档
static min(min: number): ValidatorFn 
static max(max: number): ValidatorFn 

min()/max() is a static function that accepts a number parameter and returns A validator function that returns an error map with the min/max property if the validation check fails, otherwise null.

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

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

在 formControl 中使用 max 验证器,(有关更多信息,click here

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

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

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

Angular 有 min and max 个验证器,但仅适用于响应式表单。正如文档中所说:"The validator exists only as a function and not as a directive."

为了能够在模板驱动的表单中使用这些验证器,您需要创建自定义指令。在我的实现中,我使用 @HostBinding 来应用 HTML min/max-属性。我的 selector 也非常具体,可以防止对使用 minmax 输入实现 ControlValueAccessor 的自定义表单控件进行验证 运行(例如 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);
  }
}

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

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

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

年龄始终在 1 到 18 岁之间。

在我的模板驱动形式 (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 作为指令,并且仅对正数施加正则表达式限制。

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

自定义最小值-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.

自定义最大-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 属性。现在找到用于验证的代码片段。

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

我已经为 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)
  }
}

这个问题已经有人回答了。我想扩展@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);
    }

}

我的严格编译器版本

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

}