Input type number “only numeric value” validation

后端 未结 5 1713
耶瑟儿~
耶瑟儿~ 2021-02-03 17:43

How can I validate an input of type=\"number\" to only be valid if the value is numeric or null using only Reactive Forms (no directives)?
Only numbers

相关标签:
5条回答
  • 2021-02-03 17:54

    Sometimes it is just easier to try something simple like this.

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

    Hope this helps.

    updated as per comment, You need to to call the validator like this

    number: new FormControl('',[this.validateNumber.bind(this)])
    

    The bind(this) is necessary if you are putting the validator in the component which is how I do it.

    0 讨论(0)
  • 2021-02-03 18:01

    I had a similar problem, too: I wanted numbers and null on an input field that is not required. Worked through a number of different variations. I finally settled on this one, which seems to do the trick. You place a Directive, ntvFormValidity, on any form control that has native invalidity and that doesn't swizzle that invalid state into ng-invalid.

    Sample use: <input type="number" formControlName="num" placeholder="0" ntvFormValidity>

    Directive definition:

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

    The challenge was to get the ElementRef from the FormControl so that I could examine it. I know there's @ViewChild, but I didn't want to have to annotate each numeric input field with an ID and pass it to something else. So, I built a Directive which can ask for the ElementRef.

    On Safari, for the HTML example above, Angular marks the form control invalid on inputs like "abc".

    I think if I were to do this over, I'd probably build my own CVA for numeric input fields as that would provide even more control and make for a simple html.

    Something like this:

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

    PS: If there's a better way to grab the FormControl for the directive, I'm guessing with Dependency Injection and providers on the declaration, please let me know so I can update my Directive (and this answer).

    0 讨论(0)
  • 2021-02-03 18:04

    You need to use regular expressions in your custom validator. For example, here's the code that allows only 9 digits in the input fields:

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

    Take a look at a sample app here:

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

    0 讨论(0)
  • 2021-02-03 18:06

    In HTML file you can add ngIf for you pattern like 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>
    

    In .ts file you can add the Validators pattern - "^[0-9]*$"

    this.Mobile = new FormControl('', [
      Validators.required,
      Validators.pattern("^[0-9]*$"),
      Validators.minLength(8),
    ]);
    
    0 讨论(0)
  • 2021-02-03 18:12

    The easiest way would be to use a library like this one and specifically you want noStrings to be true

        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;   
          } 
        }
    
    0 讨论(0)
提交回复
热议问题