oyvindym oyvindym - 28 days ago 9
AngularJS Question

Constructing RegExp in JavaScript from object property (string)

I am attempting to create a input directive in Angular which can be configured from a remote endpoint.

The object below should result in a input-field with

type=text
and should only be set to valid if the input is a 6-digit number.

{
inputfield: {
"name": "6-digit code",
"type": "text",
"pattern": "/^\d{6}$/"
}
}


The problem I am encountering is that if I use
$setValidity
and check the value with a Regex generated from
pattern
I get the following:

var pattern = new RegExp("^\d{6}$");

console.log(pattern.toString());
=> "/^d{6}$/"


Which is fine, as
\
is escaped as expected. I do have access to the endpoint delivering the data. This endpoint is a REST-endpoint written in Java. So at the endpoint the Regex is defined as follows:

String regex = "/^\\d{6}$/";


So, to sum up:

From endpoint: "/^\\d{6}$/"
Received at client: "/^\d{6}$/"
Constructing RegExp from the received object gives: "/^d{6}$/"
Wanted RegExp: /^\d{6}$/


Can this be achieved without declaring the Regex at the endpoint with quadrouple slashes (i.e.
"/^\\\\d{6}$/"
)?

Answer

The object below should result in a input-field with type=text and should only be set to valid if the input is a 6-digit number.

{
    "name": "6-digit code",
    "type": "text",
    "pattern": "/^\d{6}$/"
}

In JavaScript, the source text "/^\d{6}$/" produces exactly the same string as "/^d{6}$/". Since \d isn't a defined escape sequence, it's just d with an escape in front of it. In JavaScript, if a character doesn't need escaping but you escape it anyway, the escape is just ignored. (In contrast with JSON, which is strict and would complain about the text above.)

So at the endpoint the Regex is defined as follows:

String regex = "/^\\d{6}$/";

That means whatever is producing the JSON is doing so incorrectly, because if it were doing so correctly, the backslash before the d would be escaped and the source text of the object would look like this:

{
    "name": "6-digit code",
    "type": "text",
    "pattern": "/^\\d{6}$/"
}

...would work correctly with the RegExp constructor once (as squint pointed out in a now-deleted comment) you remove the leading and trailing slashes (otherwise, the regex will try to match / literally).

So the fix here is to fix whatever's producing the incorrect JSON, ideally by using a proper JSON library (Gson, Jackson, ...).