Forms “输入类型编号”;仅限数值“;验证
如何验证输入的Forms “输入类型编号”;仅限数值“;验证,forms,angular,validation,Forms,Angular,Validation,如何验证输入的type=“number”仅在值为数字或空时才有效(仅使用被动形式(无指令)? 只有数字[0-9]和。是允许的,没有“e”或任何其他字符 到目前为止我所尝试的: 模板: 自定义验证程序: 问题是,当用户输入的不是数字(“123e”或“abc”)时,FormControl的值变为null,请记住,我不希望该字段为必填字段,因此如果该字段确实为空null值应为有效值。 跨浏览器支持也很重要(Chrome的数字输入字段不允许用户输入字母-除了“e”,但FireFox和Safari允许)
type=“number”
仅在值为数字或空时才有效(仅使用被动形式(无指令)?只有数字
[0-9]
和。是允许的,没有“e”或任何其他字符
到目前为止我所尝试的: 模板: 自定义验证程序: 问题是,当用户输入的不是数字(“123e”或“abc”)时,FormControl的值变为
null
,请记住,我不希望该字段为必填字段,因此如果该字段确实为空null
值应为有效值。跨浏览器支持也很重要(Chrome的数字输入字段不允许用户输入字母-除了“e”,但FireFox和Safari允许)
最简单的方法是使用这样的库,特别是希望
noStrings
为真
export class CustomValidator{ // Number only validation
static numeric(control: AbstractControl) {
let val = control.value;
const hasError = validate({val: val}, {val: {numericality: {noStrings: true}}});
if (hasError) return null;
return val;
}
}
您需要在自定义验证器中使用正则表达式。例如,以下代码只允许输入字段中有9位数字:
function ssnValidator(control: FormControl): {[key: string]: any} {
const value: string = control.value || '';
const valid = value.match(/^\d{9}$/);
return valid ? null : {ssn: true};
}
请在此处查看示例应用程序:
有时候,尝试像这样简单的事情更容易
validateNumber(control: FormControl): { [s: string]: boolean } {
//revised to reflect null as an acceptable value
if (control.value === null) return null;
// check to see if the control value is no a number
if (isNaN(control.value)) {
return { 'NaN': true };
}
return null;
}
希望这有帮助
根据评论更新,
您需要像这样调用验证器
number: new FormControl('',[this.validateNumber.bind(this)])
如果要将验证器放入组件中(我就是这样做的),那么绑定(这个)是必要的。在HTML文件中,您可以像这样为自己添加ngIf模式
<div class="form-control-feedback" *ngIf="Mobile.errors && (Mobile.dirty || Mobile.touched)">
<p *ngIf="Mobile.errors.pattern" class="text-danger">Number Only</p>
</div>
我也有一个类似的问题:我希望输入字段上的数字和null不是必需的。经历了许多不同的变化。我最终决定了这一个,这似乎是成功的。您可以在任何具有本机无效性且不会将无效状态转换为ng invalid的窗体控件上放置一个指令,
ntvFormValidity
样本使用:
指令定义:
import { Directive, Host, Self, ElementRef, AfterViewInit } from '@angular/core';
import { FormControlName, FormControl, Validators } from '@angular/forms';
@Directive({
selector: '[ntvFormValidity]'
})
export class NtvFormControlValidityDirective implements AfterViewInit {
constructor(@Host() private cn: FormControlName, @Host() private el: ElementRef) { }
/*
- Angular doesn't fire "change" events for invalid <input type="number">
- We have to check the DOM object for browser native invalid state
- Add custom validator that checks native invalidity
*/
ngAfterViewInit() {
var control: FormControl = this.cn.control;
// Bridge native invalid to ng-invalid via Validators
const ntvValidator = () => !this.el.nativeElement.validity.valid ? { error: "invalid" } : null;
const v_fn = control.validator;
control.setValidators(v_fn ? Validators.compose([v_fn, ntvValidator]) : ntvValidator);
setTimeout(()=>control.updateValueAndValidity(), 0);
}
}
从'@angular/core'导入{指令、主机、Self、ElementRef、AfterViewInit};
从'@angular/forms'导入{FormControlName,FormControl,Validators};
@指示({
选择器:“[ntvFormValidity]”
})
导出类NtvFormControlValidityDirective在ViewInit之后实现{
构造函数(@Host()private cn:FormControlName,@Host()private el:ElementRef){}
/*
-Angular不会为无效对象触发“更改”事件
-我们必须检查DOM对象的浏览器本机无效状态
-添加检查本机无效性的自定义验证器
*/
ngAfterViewInit(){
var-control:FormControl=this.cn.control;
//通过验证程序将本机无效桥接到ng无效
const ntvValidator=()=>!this.el.nativeElement.validity.validity?{错误:“无效”}:null;
const v_fn=control.validator;
control.setValidators(v_fn?Validators.compose([v_fn,ntvValidator]):ntvValidator);
setTimeout(()=>control.updateValueAndValidity(),0);
}
}
挑战是从FormControl获取ElementRef,以便我可以检查它。我知道有@ViewChild,但我不想用ID注释每个数字输入字段并将其传递给其他对象。因此,我建立了一个指令,可以请求ElementRef
在Safari上,对于上面的HTML示例,Angular标记表单控件在“abc”等输入上无效
我想如果我再做一遍,我可能会为数字输入字段构建自己的字段,因为这样可以提供更多的控制,并创建一个简单的html
大概是这样的:
PS:如果有更好的方法来获取指令的FormControl,我猜是通过依赖项注入和声明上的
提供程序
,请让我知道,这样我就可以更新我的指令(和这个答案)。使用指令变得很简单,可以在整个应用程序中使用
HTML
当输入包含字母时FormControls值为空时,我如何实现这一点?我编辑了答案,以了解如何实现。是的,谢谢,但这并不能解决问题的核心。如果输入包含字母
让val=control.value=null
。这是angular在类型为number时如何解析输入值的问题。如果输入是text类型,那么我的验证将非常有效。或者简单地使用let regex=/\D+/;regex.exec(“stringToT3est”)
。如果不包含数字,则返回null。但这对小数不起作用。我尝试过使用正则表达式,但这不是问题的核心。当输入类型为number,且值不是数字(“123e”或“abc”)时,FormControl的值变为null
…好的,我现在理解您的问题了,这不是CustomValidator内部的逻辑,而是如何首先获取输入而不是null。是否可以将您的输入从“类型编号”更改为“类型文本”(或者简单地将其删除并默认为“文本”)并以这种方式进行验证?用户可以输入任何字符串,但验证器可以拒绝该字符串。这就是我迄今为止解决该问题的方法。但是,当输入类型为text时,我会丢失绑定到number类型输入的浏览器功能。主要是输入在移动设备上的作用方式。我担心在这个用例中,您必须将其保留为文本,如果您想要数字增量功能,构建自定义控件并不困难。在HTML规范中,数字的输入文本将返回null值,例如“2e”,无法访问原始值:您测试过了吗?当我在CustomValidator
(在我的Plunker中)中使用id时,这不会验证。我在代码中运行了id,但没有放入Plunker,我会在几分钟后尝试设置示例,但我确实更新了答案以包含模板。请记住,问题的核心是Firefox和其他一些人的行为。如果您输入了数字,并且输入了“123e”
,则该数字不是数字,输入值为null
,但为I
number: new FormControl('',[this.validateNumber.bind(this)])
<div class="form-control-feedback" *ngIf="Mobile.errors && (Mobile.dirty || Mobile.touched)">
<p *ngIf="Mobile.errors.pattern" class="text-danger">Number Only</p>
</div>
this.Mobile = new FormControl('', [
Validators.required,
Validators.pattern("^[0-9]*$"),
Validators.minLength(8),
]);
import { Directive, Host, Self, ElementRef, AfterViewInit } from '@angular/core';
import { FormControlName, FormControl, Validators } from '@angular/forms';
@Directive({
selector: '[ntvFormValidity]'
})
export class NtvFormControlValidityDirective implements AfterViewInit {
constructor(@Host() private cn: FormControlName, @Host() private el: ElementRef) { }
/*
- Angular doesn't fire "change" events for invalid <input type="number">
- We have to check the DOM object for browser native invalid state
- Add custom validator that checks native invalidity
*/
ngAfterViewInit() {
var control: FormControl = this.cn.control;
// Bridge native invalid to ng-invalid via Validators
const ntvValidator = () => !this.el.nativeElement.validity.valid ? { error: "invalid" } : null;
const v_fn = control.validator;
control.setValidators(v_fn ? Validators.compose([v_fn, ntvValidator]) : ntvValidator);
setTimeout(()=>control.updateValueAndValidity(), 0);
}
}
<input type="text" placeholder="Enter value" numbersOnly>
@Directive({
selector: "[numbersOnly]"
})
export class NumbersOnlyDirective {
@Input() numbersOnly:boolean;
navigationKeys: Array<string> = ['Backspace']; //Add keys as per requirement
constructor(private _el: ElementRef) { }
@HostListener('keydown', ['$event']) onKeyDown(e: KeyboardEvent) {
if (
// Allow: Delete, Backspace, Tab, Escape, Enter, etc
this.navigationKeys.indexOf(e.key) > -1 ||
(e.key === 'a' && e.ctrlKey === true) || // Allow: Ctrl+A
(e.key === 'c' && e.ctrlKey === true) || // Allow: Ctrl+C
(e.key === 'v' && e.ctrlKey === true) || // Allow: Ctrl+V
(e.key === 'x' && e.ctrlKey === true) || // Allow: Ctrl+X
(e.key === 'a' && e.metaKey === true) || // Cmd+A (Mac)
(e.key === 'c' && e.metaKey === true) || // Cmd+C (Mac)
(e.key === 'v' && e.metaKey === true) || // Cmd+V (Mac)
(e.key === 'x' && e.metaKey === true) // Cmd+X (Mac)
) {
return; // let it happen, don't do anything
}
// Ensure that it is a number and stop the keypress
if (e.key === ' ' || isNaN(Number(e.key))) {
e.preventDefault();
}
}
}