Home > Enterprise >  Regex pattern, optional plus character at start of line not matching
Regex pattern, optional plus character at start of line not matching

Time:01-19

I am trying to control a text input field in a react application by only allowing an empty string, digits or an optional plus character at the start.

The regex pattern I am using is the following:

export const phoneNumberTestPattern = new RegExp('^\\ ?\\d ?$');

This pattern is used to test the inputs value whenever the input is changed

onChange={ (e) => {
    if (e.target.value === '' || phoneNumberTestPattern.test(e.target.value)) {
       field.onChange(e.target.value);
   }
}}

The pattern is working correctly for allowing only digits. But the optional plus character at the start is not being matched when the onChange event parameter returns a value as e.target.value.

The event.target.value does return the as a value when typed in, but the test pattern does not recognize it as something that matches so the field.onChange method is never fired.

I dont understand what the reason for this is, and why the pattern is not matching a plus character at the start of the string being sent to it. Could it be possible the value I am sending to the test pattern is a string and I am trying to match it against a plus operator ?

Any help would be greatly appreciated.

CodePudding user response:

The error is on \d ?. It does not mean an optional sequence of digits. It means a sequence of at least one digit, not greedy.

The * and quantifiers are, by default, greedy. This means that they attempt to match as much as possible.

For example, the regex a matches the entire string aaa. The qualifier makes the a before it to match all a characters from the input string.
By adding a ? after , the qualifier becomes lazy and the regex a ? matches only the first a from the input string.

Check it below:

const reGreedy = /a /;
const reLazy = /a ?/;

console.log(reGreedy.exec('aaa'));
console.log(reLazy.exec('aaa'));

This means that your regex matches the input string only if the input string contains at least one digit at the end.

There are two ways to achieve what you need. One of them is to wrap \d in parentheses, like this: (\d )?. This way \d matches a sequence of one or more digits and the ? after it tells that this sequence is optional.

The same thing can be achieved by using * instead of , and ? is not needed any more in this case. \d* matches a sequence of zero or more digits.

Also, if you create a RegExp using a regex literal there is no need to escape the backslash.

Be aware that this regex also matches the empty string (now both the and the number are optional). Your check against the empty string can be removed from the code.

All in all, your code should be like:

export const phoneNumberTestPattern = /^\ ?\d*$/;

onChange={ (e) => {
    if (phoneNumberTestPattern.test(e.target.value)) {
       field.onChange(e.target.value);
   }
}}

Check the regex online.

CodePudding user response:

Maybe u can try this regex pattern

^(?: )?\d $

CodePudding user response:

Like other answers say, you could use /^(?:|\ ?\d )$/

const populated = ' 123456'
const unpopulated = ''

const pattern = /^(?:|\ ?\d )$/

console.log(`populated: ${pattern.test(populated)}`)
console.log(`unpopulated: ${pattern.test(unpopulated)}`)

But an alternative is to use the pattern attribute of the <input> tag:

input:valid {
    background-color: palegreen;
}

input:invalid {
    background-color: lightpink;
}
<input id="id-inp" type="tel" pattern="^\ ?\d ?$">

  • Related