输入类型编号"仅数字值"验证

时间:2017-07-12 12:37:21

标签: forms angular validation

如何仅使用Reactive Forms (无指令)来验证type="number"的输入是否仅在数值为null时有效或为null? 只有数字[0-9]和。是允许的,不是" e"或任何其他角色。

到目前为止我尝试过的事情:

模板:

<form [formGroup]="form" novalidate>
    <input type="number" formControlName="number" id="number">
</form>

组件:

export class App {
  form: FormGroup = new FormGroup({});

  constructor(
    private fb: FormBuilder,
  ) {
    this.form = fb.group({
      number: ['', [CustomValidator.numeric]]
    })
  }
}

的CustomValidator:

export class CustomValidator{
  // Number only validation
  static numeric(control: AbstractControl) {
    let val = control.value;

    if (val === null || val === '') return null;

    if (!val.toString().match(/^[0-9]+(\.?[0-9]+)?$/)) return { 'invalidNumber': true };

    return null;
  }
}

Plunker

问题是用户输入的内容不是数字(&#34; 123e&#34;或&#34; abc&#34;) FormControl的值变为null,请注意我不希望该字段是必需的,因此如果该字段确实为空null值应该有效。

  

跨浏览器支持也很重要(Chrome的数字输入字段不允许用户输入字母 - 除了&#34; e&#34;,但FireFox和Safari会这样做。)

7 个答案:

答案 0 :(得分:18)

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

在.ts文件中,您可以添加验证器模式 - &#34; ^ [0-9] * $&#34;

this.Mobile = new FormControl('', [
  Validators.required,
  Validators.pattern("^[0-9]*$"),
  Validators.minLength(8),
]);

答案 1 :(得分:1)

最简单的方法是使用像one这样的库,特别是你希望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;   
      } 
    }

答案 2 :(得分:0)

您需要在自定义验证程序中使用正则表达式。例如,这里的代码只允许输入字段中的9位数字:

function ssnValidator(control: FormControl): {[key: string]: any} {
  const value: string = control.value || '';
  const valid = value.match(/^\d{9}$/);
  return valid ? null : {ssn: true};
}

在这里查看一个示例应用程序:

https://github.com/Farata/angular2typescript/tree/master/Angular4/form-samples/src/app/reactive-validator

答案 3 :(得分:0)

有时候尝试像这样简单的事情会更容易。

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

如果要将验证器放在组件中,那么绑定(this)是必要的。

答案 4 :(得分:0)

我也有类似的问题:我想要在不需要的输入字段上输入数字和null。经历了许多不同的变化。我终于选择了这个,似乎可以解决问题。您将ntvFormValidity指令放在具有本机无效且不会将该无效状态转换为ng-invalid的任何表单控件上。

样品使用: <input type="number" formControlName="num" placeholder="0" 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);
  }
}

面临的挑战是从FormControl获取ElementRef,以便我可以对其进行检查。我知道有@ViewChild,但我不想用ID注释每个数字输入字段并将其传递给其他东西。因此,我建立了一个可以要求ElementRef的指令。

在Safari上,对于上面的HTML示例,Angular将表单控件标记为对诸如“ abc”之类的输入无效。

我认为,如果我要这样做,我可能会为数字输入字段构建自己的CVA,因为这将提供更多控制权并简化HTML。

类似这样的东西:

<my-input-number formControlName="num" placeholder="0">

PS:如果有更好的方法来获取该指令的FormControl,我猜想是依赖注入和声明中的providers,请让我知道,以便我可以更新我的指令(以及此答案)

答案 5 :(得分:0)

使用指令变得容易并且可以在整个应用程序中使用

HTML

<input type="text" placeholder="Enter value" numbersOnly>

由于 .keyCode().which() 已弃用,因此使用 .key() 检查代码 转介from

指令:

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

答案 6 :(得分:0)

尽量减少输入,只允许输入 0 到 9 之间的数字。这在 Angular Cli 中对我有用

<input type="number" oninput="this.value=this.value.replace(/[^\d]/,'')"  min=0>