I'm making a Google Form via Apps Script and need to set a field to only accept US 10-digit phone numbers. I found this regular expression which works if I set it via the Form Editor: ^(\+0?1\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$
.
But again, I need this to work from Apps Script. My code snippet is as follows:
let form = FormApp.create("new Order");
let phoneNumber = form.addTextItem().setTitle("Textable phone number").setRequired(true);
phoneNumber.setValidation(FormApp.createTextValidation()
.requireTextMatchesPattern("^(\+0?1\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$")
.build());
This throws Exception: Invalid data updating form.
When I change it to .requireTextMatchesPattern(/^(\+0?1\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$/)
the script runs and completes, but then it's impossible to fill out the form because a standard phone number throws an error saying must match pattern.
So, how do I set a regular expression pattern in Apps Script that will properly allow input?
That question refers to the requireTextMatchesPattern()
method that expects a regex string rather than a RegExp
object. The problem is that Javascript strings and regexes both use the backslash \
to escape certain special characters, but not all the escapes have the same meaning in the two contexts.
There are many special characters in regular expressions, including:
.*+?^${}()|[]\
The regex in the question uses some of those characters literally, such as searching for an instance of +
. To do that, you must escape the special character by adding a backslash \
prefix. That is easy to do when you use a JavaScript regex literal, but more tricky when you need to use a JavaScript string literal. Notably, to get an actual backslash in a JavaScript string literal, you need to escape it as in \\
.
Since the string regex requires backslashes, you need to double those backslashes in the JavaScript string in order for them to be interpreted correctly. To get the regex string ^(\+0)$
, where +
is a literal rather than a special character, you need to use the JavaScript string '^(\\+0)$'
.
To make the regex string work, do the same with all special characters you need to escape in the string, like this:
function getFormWithRegexValidation() {
const phoneNumberPattern = '^(\\+0?1\\s)?\\(?\\d{3}\\)?[-.\\s]\\d{3}[-.\\s]\\d{4}$';
const phoneNumberValidation = FormApp.createTextValidation()
.requireTextMatchesPattern(phoneNumberPattern)
.build();
const form = FormApp.create('new Order');
form.addTextItem()
.setTitle('Textable phone number')
.setRequired(true)
.setValidation(phoneNumberValidation);
return form;
}
In the event you're not working with string literals but need to escape all regex special characters in a string variable, for example in the input received from a user, use this utility function:
/**
* Escapes special characters such as \ ( ) [ ].
*
* @param {String} string The text string to escape.
* @return {String} The escaped text string.
*/
function escapeRegExCharacters_(string) {
// version 1.1, written by --Hyde, 9 November 2018
// - adapted from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
return String(string).replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}