RohanArihant
RohanArihant

Reputation: 2750

How to restrict input textbox to enter numbers only in Angular2 form?

I have to restrict user to enter only numbers in a field in Angular2->form I have solution but backspace is not working in input field Can anybody have proper solution for that?

form.html

<input (keypress)="keyPress($event)" minlength="8" maxlength="15" required />

form.component.ts

keyPress(event: any) {
    const pattern = /[0-9\+\-\ ]/;
    let inputChar = String.fromCharCode(event.charCode);
    // console.log(inputChar, e.charCode);
       if (!pattern.test(inputChar)) {
       // invalid character, prevent input
           event.preventDefault();
      }
 }

On kepress event it restrict user to enter only numbers but problem with this code is backspace, tab keys are not working.So, this code is not as per my expectation...

Upvotes: 3

Views: 23687

Answers (8)

jinavar1
jinavar1

Reputation: 363

I made a directive to prevent specific input, similar to others posted here and in other posts. I based mine in this article, but made a few changes to avoid using the deprecated keyCode attribute, among other things.

I also lifted the restriction on the allowed keyboard commands (any combination of keys containing Ctrl, Command, Shift or Alt) because it may lead to unintended restrictions (like being unable to execute the undo/redo command).

Here is the directive:

import { Directive, HostListener } from '@angular/core';

@Directive({
  selector: '[inputDigitsOnly]',
})
export class InputDigitsOnlyDirective {
  private static readonly allowedKeyCodes = [
    "Backspace",
    "Delete",
    "Insert",
    "ArrowUp",
    "ArrowRight",
    "ArrowDown",
    "ArrowLeft",
    "Tab",
    "Home",
    "End",
    "Enter",
    "Digit1",
    "Digit2",
    "Digit3",
    "Digit4",
    "Digit5",
    "Digit6",
    "Digit7",
    "Digit8",
    "Digit9",
    "Digit0",
    "Numpad0",
    "Numpad1",
    "Numpad2",
    "Numpad3",
    "Numpad4",
    "Numpad5",
    "Numpad6",
    "Numpad7",
    "Numpad8",
    "Numpad9",
  ];

  @HostListener('keydown', ['$event'])
  onKeyDown(e: KeyboardEvent) {
    // This condition checks whether a keyboard control key was pressed.
    // I've left this 'open' on purpose, because I don't want to restrict which commands
    // can be executed in the browser. For example, It wouldn't make sense for me to prevent
    // a find command (Ctrl + F or Command + F) just for having the focus on the input with
    // this directive.
    const isCommandExecution = e.ctrlKey || e.metaKey || e.shiftKey || e.altKey;
    const isKeyAllowed = InputDigitsOnlyDirective.allowedKeyCodes.indexOf(e.code) !== -1;

    if (!isCommandExecution && !isKeyAllowed) {
      e.preventDefault();
      return;  // let it happen, don't do anything
    }
  }
}

Then you just need to add the directive in the input:

<input type="text" inputDigitsOnly>

You can change it to fit your needs. You can check the list of available key codes here.

Hope it helps.

Upvotes: 2

Dani
Dani

Reputation: 807

I created a directive that will only allow you to type numbers only.

import { Directive, ElementRef, HostListener, Input,OnInit,Renderer } from '@angular/core';


@Directive({
   selector: 'input[app-numeric-field]'
})
export class NumericValidatorDirective implements OnInit {
  @Input('app-numeric-field') maxLength: string;

  constructor(private elementRef: ElementRef,private _renderer: Renderer) {}

  ngOnInit(): void {
     this._renderer.setElementAttribute(this.elementRef.nativeElement, 'maxlength', this.maxLength);
  }

  @HostListener('keydown', ['$event']) onKeyDown(event) {
     let e = <KeyboardEvent> event;
        if ([46, 8, 9, 27, 13, 110].indexOf(e.keyCode) !== -1 ||
           // Allow: Ctrl+A
           (e.keyCode === 65 && (e.ctrlKey || e.metaKey)) ||
           // Allow: Ctrl+C
           (e.keyCode === 67 && (e.ctrlKey || e.metaKey)) ||
           // Allow: Ctrl+V
           (e.keyCode === 86 && (e.ctrlKey || e.metaKey)) ||
           // Allow: Ctrl+X
           (e.keyCode === 88 && (e.ctrlKey || e.metaKey)) ||
           // Allow: home, end, left, right
           (e.keyCode >= 35 && e.keyCode <= 39)) {
           // let it happen, don't do anything
         return;
       }
         // Ensure that it is a number and stop the keypress
       if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
           e.preventDefault();
       }
    }
}

Then you can use it like this.

<input matInput app-numeric-field>

Upvotes: 1

Lars
Lars

Reputation: 3930

Please do not use String.fromCharCode(event.keyCode) any longer, it is marked deprecated MDN and it seems to not working right in Firefox 58. A simple function, tested on Chrome & Firefox:

onKeypress(event: any) {
  const keyChar = event.key;

  let allowCharacter: boolean;
  if (keyChar === "-" && event.target.selectionStart !== 0) {
    allowCharacter = false;
  }
  else if (
    keyChar === "Tab" ||
    keyChar === "Enter" ||
    keyChar === "Backspace" ||
    keyChar === "ArrowLeft" ||
    keyChar === "ArrowRight" ||
    keyChar === "Delete") {
    allowCharacter = true;
  }
  else {
    allowCharacter = (keyChar >= '0' && keyChar <= '9');
  }

  if (!allowCharacter) {
    event.preventDefault();
  }
}

I'm also not happy with this code and hope there exists a better library for this in Angular.

Upvotes: 0

Ayush Gupta
Ayush Gupta

Reputation: 23

you can use this way too

keyPress(event: any) {

        const pattern = /[0-9\+\-\ ]/;
        let inputChar = String.fromCharCode(event.charCode);

            if (!pattern.test(inputChar) && event.charCode != '0') {
                event.preventDefault();
            }
    }

Upvotes: 1

spambo01
spambo01

Reputation: 31

How about using the html5 tag? <input type="number">
It 's supported from all browsers.

https://www.w3schools.com/html/html_form_input_types.asp

Upvotes: 1

RohanArihant
RohanArihant

Reputation: 2750

my answer is :- form.html:

form.component.ts

restrictNumeric = function (e) {
     var input;
     if (e.metaKey || e.ctrlKey) {
        return true;
     }
     if (e.which === 32) {
        return false;
     }
     if (e.which === 0) {
        return true;
     }
     if (e.which < 33) {
        return true;
     }
     input = String.fromCharCode(e.which);
     return !!/[\d\s]/.test(input);
 }

Upvotes: 0

nyedidikeke
nyedidikeke

Reputation: 7648

You can achieve that using regex the following way:

var numbersOnly = document.getElementById("numbersOnly");
numbersOnly.onkeyup = function myFunction() {
    numbersOnly.value = numbersOnly.value.replace(/[^0-9]/g, '');
};
<input id="numbersOnly" minlength="8" maxlength="15" required>

Upvotes: 1

user268396
user268396

Reputation: 12006

Backspace will not work because: event.charCode will not map to one of the digits 0-9 for the backspace key.

You need to whitelist the backspace (i.e. keyCode = 8). Something like this (off the top of my head):

if(event.keyCode != 8 && !pattern.test(inputChar)) {
   event.preventDefault();
}

Upvotes: 0

Related Questions