3

I'll try to explain the problem step by step.

I wrote some custom validators in AngularJS both as directives and as a service. Here's the code:

//validators.service.ts

@Injectable()
export class ValidatorsService {

  constructor() { }

  email():ValidatorFn {
    return (control: FormControl) => {
      if (!isNullOrUndefined(control.value) && control.value !== '') {
        const isValid = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(control.value);
        if (isValid) return null;
        return { emailValidator: { valid: false } }
      }

      return null
    };
  }
}


//email.directive.ts
@Directive({
  selector: '[appEmailValidator]',
  providers: [
    {
      provide: NG_VALIDATORS,
      useClass: EmailValidatorDirective,
      multi: true
    }
  ]
})
export class EmailValidatorDirective implements Validator {

  validator: ValidatorFn;
  
  constructor(private validatorsService: ValidatorsService) {
    this.validator = this.validatorsService.email()
  }

  validate(c: FormControl) {
    return this.validator(c);
  }

}

which i use like this:

<input 
  pInputText 
  id="email" 
  name="email" 
  appEmailValidator 
  [(ngModel)]="mymodel" 
  required>

or like this:

//*.component.html

<input 
  type="email" 
  pInputText 
  id="email"
  formControlName="email" name="email">


//*.component.ts

ngOnInit() {
        this.actorForm = new FormGroup({
            email: new FormControl('', [this.validatorsService.email(), Validators.required]),
        });
    }

It works perfectly in terms of Regex: "[email protected]" gets accepted whereas "[email protected]" does not.

The problem comes when i type more characters (especially over 26): Chrome gets stuck, I can't enter any new character, my CPU usage goes to 100% and it basically crashes, even reloading the page becomes impossible. This doesn't happen with Safari for example.

So:

• I tried to convert my service into simple functions, nothing has changed.

• I removed the PrimeNg directive thinking it might cause the problem, nothing.

• I removed the directive and I tried to use the HTML pattern, nothing.

• I removed the entire ngModel directive and it worked, so it has to do with Angular somehow. Also, it works by binding the event (change)=inputChanged($event) and updating the model with:

inputChanged(e){
  this.model = event.target.value
}

• Then, I tried to remove just the event binding: [ngModel]="model" using HTML input pattern, nope.

• I updated my Angular version to the latest (I'm using version 4.3.1), nothing.

• I changed my regex into /.+/ and it worked, and, even if it's useless, i got that the problem was related to my regex and ngModel.

Therefore, I read these questions:

HTML input pattern not working

Regex on Chrome pattern input validation

and even if i don't have any errors and, as I said, it works initially, I converted every \. into . , again, nothing has changed.

What's wrong with my regex? Have you ever encountered this problem? Do you have a workaround?

I'd like to use Angular features but it seems unlikely.

UPDATE

It seems I'm not the only one who had to deal with this error:

https://github.com/angular/angular/issues/12753

Angularjs input field is getting stuck on typing in google chrome

but it's still unsolved.

• I tried to debounce the input as someone in github has suggested, it doesn't work.

• I literally copied and pasted the same Regex Angular uses as email validator:

/^(?=.{1,254}$)(?=.{1,64}@)[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/

and it worked.

Is my regex inefficient? If that were the case, it wouldn't work in other browsers either, isn't it?

UPDATE

• I bound the input and keyup events and moved my logic in JS (without HTML pattern, but I think it doesn't matter). It doesn't work, even with 1s of debounce. Yet, as i said, the change event works.

• I tried with myRegex.test(myLongString) just to understand whether this has to deal with events or not. Surprisingly, chrome gets stuck anyway. I don't know why the change event works. Maybe, I haven't tested it properly.

The only way I solved this is by modifying my regex:

/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/

(https://emailregex.com/)

which is way better than the Angular one.

Just for reference, I post some tests I made.

valida => valid

invalida => invalid

New working regex (emailregex.com)

New working regex (emailregex.com)

My old (not working) regex New working regex (emailregex.com)

Angular regex

Angular Regex

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.