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 < 0
和 <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),因为许多人已经在使用 min
和 max
,但并非所有人都在使用期待它的验证。有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()/max()是接受数字参数和的静态函数>返回 一个验证器函数,它返回带有 min/max 属性的错误映射 如果验证检查失败,否则为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)]);
【讨论】:
【参考方案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 支持 min 和 max 验证器: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 中,元素是:<input type="text" class="form-control" id="item1" formControlName="templateItem1">
(并且存在于 form-group
和 form
元素中),然后您可以使用 form-control-feedback
和 templateItem1.errors .dirty .touched
来获取验证消息。
它不是模板驱动的表单
来自有关 min 和 max 的 Angular 文档:“验证器仅作为函数存在,而不作为指令存在。”最小值最大值仅适用于反应形式。【参考方案11】:
Angular 有 min 和 max 验证器,但仅适用于响应式表单。正如它在文档中所说:“验证器仅作为函数存在,而不是作为指令存在。”
为了能够在模板驱动的表单中使用这些验证器,您需要创建自定义指令。在我的实现中,我使用@HostBinding
来应用 HTML min
/max
-attributes。我的selector
s 也非常具体,以防止在自定义表单控件上运行验证,这些控件使用ControlValueAccessor
实现min
或max
输入(例如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;
我们可以将 customMax 与 formControlName、formControl 和 ngModel 属性一起使用。
在模板驱动表单中使用自定义最小值和最大值验证器
我们将以模板驱动的形式使用自定义的最小和最大验证器。对于最小数量验证,我们有 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(示例