Reputation: 4756
I have to create a regex that allows the user to input only a number (using . or ,)
so these examples are both valid:
here's my current code
private regex: RegExp = new RegExp(/^\d*[\,\.]{0,1}\d{1,2}/g);
However this allows me to input 8.,5
which is obviously bad. How can I change my regex so that the user can only place 1 of the decimal characters , OR .
?
EDIT:
I've tried alot of answers, but most of them don't work (I can't place any decimal characters). Basically I'm creating a directive in angular that converts <input type="text">
to an numeric input (I can't use type="number"
)
Here's my directive code (see Angular2 - Input Field To Accept Only Numbers)
@Directive({
selector: "[OnlyNumber]"
})
export class OnlyNumberDirective {
// Allow decimal numbers. The \. is only allowed once to occur
private regex: RegExp = new RegExp(/^(?=.+)\d*(?:[\,\.]\d{1,2})?$/g);
// Allow key codes for special events. Reflect :
// Backspace, tab, end, home
private specialKeys: Array<string> = ["Backspace", "Tab", "End", "Home"];
constructor(private el: ElementRef) {
}
@HostListener("keydown", ["$event"])
onKeyDown(event: KeyboardEvent) {
// Allow Backspace, tab, end, and home keys
if (this.specialKeys.indexOf(event.key) !== -1) {
return;
}
let current: string = this.el.nativeElement.value;
let next: string = current.concat(event.key);
if (next && !String(next).match(this.regex)) {
event.preventDefault();
}
}
}
and here's how I use it in my template:
<mat-form-field class="numeric-textbox">
<input matInput
OnlyNumber
#model="ngModel"
placeholder="{{ label }}"
[ngModel]="selectedValue"/>
<mat-error><ng-content></ng-content></mat-error>
</mat-form-field>
Upvotes: 1
Views: 219
Reputation: 48711
You should specify the end of input string with $
without which a partial match will happen. You shouldn't look for \d*
unless you want to match values like .5
or ,5
otherwise they will match as a valid input.
^\d+(?:[.,]\d{1,2})?$
Note: You don't need to escape dots or commas inside a character class and a quantifier like [.,]{0,1}
is literally equal to [.,]?
Live demo:
document.getElementById("number").addEventListener("keyup",function(e) {
console.log(this.value.match(/^\d+(?:[.,]\d{1,2})?$/));
});
<input type="text" id="number" placeholder="Enter a number">
Update, based on comments
^(?![.,]?$)\d*[,.]?(?:\d{1,2})?$
This allows any number optionally followed or preceded by a decimal point or comma.
Upvotes: 1
Reputation: 22817
Your regex is perfectly fine, you just need to specify the line's termination. You're currently matching 8
from 8,.5
which is likely why you're experiencing issues with your regex. I assume you're using JavaScript's test()
function and getting true
as a response for that string. Simply append $
to your regex and you'll get the correct answer. You can also simplify your regex to the following (also commented out in the snippet below). You can also probably drop the g
flag as you're trying to match the string once, not multiple times:
^\d*[,.]?\d{1,2}$
What you're matching:
var a = ['8.5', '8,5', '.5', ',5', '8.,5']
var r = /^\d*[\,\.]{0,1}\d{1,2}/g
a.forEach(function(s){
console.log(s.match(r))
})
What you should be matching:
var a = ['8.5', '8,5', '.5', ',5', '8.,5']
var r = /^\d*[\,\.]{0,1}\d{1,2}$/g
// var r = /^\d*[,.]?\d{1,2}$/
a.forEach(function(s){
console.log(s.match(r))
})
Upvotes: 0
Reputation: 3057
Try: /^(?=.+)\d*(?:[,.]\d{1,2})?$/g
let regex = /^(?=.+)\d*(?:[,.]\d{1,2})?$/g,
strings = ["5", "50", "500", ".5", ",5","5.5","5,5", "5.55", "5,55", "5.555", "5,555", "5,,5", "5..5", "5,.5", "5.,5", "5,", "5."];
strings.forEach((string) => {
console.log(`${regex} ${string.match(regex) ? `matches ${string.match(regex)}`: `has no match for ${string}`}`);
});
This will match:
From the start, lookahead to make sure that there are characters present (one or more), and then begin matching: any amount of digits (0 or more), and the following optional: a comma or a dot, and then 1 or 2 digits before the end of the string.
Upvotes: 0
Reputation: 60
The regex is correct, buy you just need to match the whole string: ^ start of the string $ end of the string
However, the regex can be improved with:
^ : for start of string
\d+ : for at least 1 digit
(
[\,\.] : 1 comma
\d{1,2} : followed by 1 digit or two
)? : keep this optionnal. We can get numbers without commas
$ : end of string
Final regex may be:
/^\d+([\,\.]\d{1,2})?$/
Upvotes: 0