Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Forms “输入类型编号”;仅限数值“;验证_Forms_Angular_Validation - Fatal编程技术网

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