Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Input type number "only numeric value" validation

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 [0-9] and . are allowed, no "e" or any other characters.


What I've tried so far:

Template:

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

Component:

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

The problem is when a user enters something that is not a number ("123e" or "abc") the FormControl's value becomes null, keep in mind I don't want the field to be required so if the field really is empty null value should be valid.

Cross browser support is also important (Chrome's number input fields do not allow the user to input letters - except "e", but FireFox and Safari do).

like image 760
Mihailo Avatar asked Jul 12 '17 12:07

Mihailo


2 Answers

In the HTML file, you can add ngIf for your 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), ]); 
like image 58
Ishara Madawa Avatar answered Sep 20 '22 19:09

Ishara Madawa


Using directive it becomes easy and can be used throughout the application

HTML

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

As .keyCode() and .which() are deprecated, codes are checked using .key() Referred from

Directive:

@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();     }   } } 
like image 20
sabin Avatar answered Sep 23 '22 19:09

sabin