0

I am using Angular 19 keydown event on Textbox. It should allow only numbers and decimals up to 2 places. Valid numbers are: 123.45, 675.1, 12345 etc.

This works properly for all keys except Spacebar. Even though I have ignored it. On clicking Spacebar, 2 three times it inserts space in Textbox. My code is below:

onKeyDown = (event:KeyboardEvent): boolean { const regex = new RegExp(/^[0-9.]*$/); if(!regex.test(event.key) && event.key.length === 1 && event.code == "Space") { event.preventDefault(); return false; } const target = event.target as HTMLInputElement; const start = target?.selectionStart || 0; const value = target.value.substring(0,start)+event.key+target.value.substring(start); const newRegex = new RegExp(/^(0|[1-9]\d*)?(\.\d{0,2})?$/ if(!newRegex.test(value) && event.key.length === 1 && event.code == "Space") { event.preventDefault(); return false; } return true; } 
1
  • Your regex should allow numbers and decimals. Don't understand why you need to check the spacebar as currently both of your if statement with event.code !== "Space" will make the if returns false when typing space. Commented Jul 5 at 8:18

3 Answers 3

2

Your regex did the jobs for allowing numbers/decimals.

The issue is both if statements with event.code !== "Space" return false when typing "Space" (key).

Just remove the event.code !== "Space" logic from both if statements. Or (only) rely on the regex without validating the typed key (value, code, and length).

// Can remove `event.key.length` for just rely on regex if (!regex.test(event.key) && event.key.length === 1) { event.preventDefault(); return false; } ... // Can remove `event.key.length` for just rely on regex const newRegex = new RegExp(/^(0|[1-9]\d*)?(\.\d{0,2})?$/) if (!newRegex.test(value) && event.key.length === 1) { event.preventDefault(); return false; } 

Demo @ StackBlitz

Sign up to request clarification or add additional context in comments.

4 Comments

Still it is taking space
Sorry, but have you tried my demo link? I am not able to replicate your case that able to type space.
This works fine on windows but not on MAC
For your case that the MAC is not working properly, sorry that I don't have a MAC device. But from what I read here, it seems the regex engine in MAC reacts differently. But as you implemented the keydown event, you can check the SpaceBar first and block it before the regex validation. if (event.code == "Space") { event.preventDefault(); return false; }
1

From my understanding of your question, in your first if-statement, you want to short-circuit if the key pressed is not a number or a space. If that is correct you should change that if-statement to:

if(!regex.test(event.key) && event.key.length === 1 || event.code === "Space") { event.preventDefault(); return false; } 

That way you return early if the key is not a number(as per your first regex) OR is a spacebar

3 Comments

yes but this also accepts space in textbox.Space should not be accepted in textbox
The clean way to do this is to validate if the user input is valid, if not, you should show a warning to the user. What you can also do, is change the textbox to type="number" so that it doesn't accept anything else besides numbers. but even in that case you need to warn the user if there are more than two decimal places
still it is taking space
1

To ensure the correct input unless what was pressed I have made an another approch:

first check step a directive and second step a Validate.service.ts:

The code snipped for the directive [InputStringRestrictive.directive.ts} is:

 import {Directive, HostListener} from '@angular/core'; @Directive({ selector: '[jgInputStringRestriction]', standalone: true }) export class jgInputStringRestrictionDirective { constructor() { } @HostListener('keydown', ['$event']) onKeyDown(event: KeyboardEvent) { if (event.key === '0') { } else if (event.key === '1') { } else if (event.key === '2') { ... } else if (event.key === '9') { } else if (event.key === ',') { } else if (event.key === '.') { } else if (event.key === '_') { } else if (event.key === '-') { } else if (event.key === '+') { // } else if (event.key === '*') { // } else if (event.key === '/') { // } else if (event.key === '^') { } else if (event.key === 'Backspace') { } else if (event.key === 'Insert') { } else if (event.key === 'ArrowLeft') { } else if (event.key === 'ArrowRight') { } else if (event.key === 'Delete') { } else if (event.key === ' ') { // delete option, if only numbers are allowed } else if (event.key === 'a') { } else if (event.key === 'b') { ... } else if (event.key === 'ü') { } else if (event.key === 'ö') { } else if (event.key === 'A') { } else if (event.key === 'B') { ... } else if (event.key === 'Y') { } else if (event.key === 'Z') { } else { event.preventDefault(); } } } 

and second snipset for validation (As in German will , instead . )

 validate(val: number | string): number | string { val === typeof 'number' ? (this.x = parseFloat(val.replace(/,/, '.'))) : null; return val; } 
 I understand, that is a totally other way to do and will not answer your redux problem, but whitespace is no problem anymore. 

The example is given on stackblitz : https://stackblitz.com/edit/stackblitz-starters-rywp1el8?file=src%2Fmain.ts,src%2FInputRestriction.directive.ts

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.