Update: 9/27/23 - I am STILL running into this issue.
Consider the following:
- You are using Angular reactive forms, and are using some built in features, like out of the box Validators.
- You use something like the following.
form.forEach((formField: any) => {
let validatorsArray = formField.validators?.reduce((validators: any, validator: any) => {
switch(validator.type){
case 'required':
validators.push(Validators.required);
break;
case 'pattern':
validators.push(Validators.pattern(new RegExp(validator.value)));
break;
where each validator is an object I've defined on our server like so (for example):
{
"name": "lowercaseandunderscore"
"value": "^[a-z_]*$",
"type": "pattern",
"error": "Column names must only contain lower case letters and underscores"
}
Now, one would assume this would inherently work using reactive forms, but it does not! It falls into the same pit as the post in 2021 below. Don't be fooled!
I came across this today.
Oddly, what works is the following:
form.forEach((formField: any) => {
let validatorsArray = formField.validators?.reduce((validators: any, validator: any) => {
switch(validator.type){
case 'required':
validators.push(Validators.required);
break;
case 'pattern':
validators.push(Validators.pattern(new RegExp(/^[a-z_]*$/)));
break;
This does not fail every other time!
But, if you are creating a Regex from using the class, using a STRING... watch out. You'll have to do something like this.
form.forEach((formField: any) => {
let validatorsArray = formField.validators?.reduce((validators: any, validator: any) => {
switch(validator.type){
case 'required':
validators.push(Validators.required);
break;
case 'pattern':
validators.push(this.testValue(validator));
break;
where your testValue function is the following:
private testValue(validator: any): ValidatorFn {
return (control: AbstractControl) => {
let returnVal = null;
if(control.value){
//NOTE the use of parenthesis around the RegExp below.
if((new RegExp(validator.value, 'gm').test(control.value))){
return null;
} else {
return {[validator.name]: validator.error};
}
}
return returnVal;
}
}
As I was working through this today, I honestly thought "surely I can't be facing that same exact problem with regexes...". Turns out, I was.
There is something to be said for every time you create a RegExp with a string. Just wrap it in parenthesis. For whatever reason, creating it without a string literal works like it should.
I hope this hammers that point home.
Essentially, regexes seem to misbehave when created from string literals, and seem to be just fine when created NOT from a string.
///End of update
This seems to still be an issue in August of 2021... I just want to share some things I have learned before stumbling upon this question and answer. I was baffled by this problem and had no meaningful way forward - until now.
It doesn't matter whether you use exec()
or test()
or match()
. The regex still doesn't work properly on every other occurrence.
It doesn't matter if you set the regex with
let reg = new RegExp(/<table(\s*[^>]*)>/g);
or with const
. Doesn't matter if you set it globally or locally either...
What does work to bypass this problem is wrapping your regex statement in parenthesis in your loop like so:
Object.keys(table).forEach(key => {
if((new RegExp(/<table(\s*[^>]*)>/g)).test(___your test string___)){
//Do what you need to do
}
});
Remove the parenthesis around the Regex, and watch every other one fail....
Thank you so much for the answer @Nick Craver and the comment @prototype!
This exact Regex was what was giving me trouble. It would work for one object, and fail for the subsequent object, and it made no sense. I am only here to say that this is still very relevant in 2021.
id
with something static and see if that works. – Anhydrous