Reputation: 3092
I have a normal reactive form for an email address which uses regex to check that its an email address in the correct format:
this.fBuilder.group({
email: [null, [Validators.required, Validators.pattern("[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])+")]],
});
However we had a rare situation where the back end needed to make up fake email address like this one:
ANS-ANS-ANS-ANS-ANS-ANS-ANS-ANS-xopnqs.xxxxxxxxxxxxxxxxhicken@qhahlaneinu.xxxxxxxxxxxxxxxxco.xxxxxxxxxxxxxxxxukxxxxxxxxxxxxxxxx
And it crashes the page. I know this wouldn't happen in the normal world, but is there a way I can amend the regex without this crashing the page? The moment the email address changes to something normal like [email protected]
it's all fine, so I definitely know it's one of those rare situations where the data is crashing the page.
Upvotes: 0
Views: 328
Reputation: 944
It is very interesting and valuable question. The problem is NOT about Reactive form validation. It seems the pattern is too complex for the browser to compute.
For such a cpu-intensive computation, we use Web Workers.
Web Worker provides more responsive experience to clients.
Web worker is a standalone process that works background independent from the main thread so the browser does not lock.
Here is the solution for your problem.
/// <reference lib="webworker" />
// web worker class can be generated using by ng-cli
// ng g web-worker
const emailPattern = /[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])+/;
// When the user posts a message to this worker,
// Worker will process the message payload and send it back to the worker that registered to this worker file.
addEventListener('message', ({ data }) => {
const response = emailPattern.test(data.payload);
postMessage({
type: 'email',
payload: response,
});
});
import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit, OnDestroy {
worker!: Worker;
formGroup!: FormGroup;
ngOnInit() {
// registering the worker to the validator.worker.
this.worker = new Worker('./validator.worker', { type: 'module' });
const emailControl = new FormControl('', [], (c) => {
return new Promise((resolve, reject) => {
let isEmailFieldValid: any = null;
// Adding listener to validator.worker response.
this.worker.onmessage = ({ data }) => {
if (data.payload) {
isEmailFieldValid = null;
return;
}
isEmailFieldValid = { email: 'Email is invalid.' };
};
// Posting our first message to the validator.worker.
// it will post back the validation result which we are listening above.
this.worker.postMessage({ type: 'email', payload: c.value });
// we need to wait for the validation result for a while.
setTimeout(() => {
resolve(isEmailFieldValid);
}, 200);
});
});
this.formGroup = new FormGroup({
email: emailControl,
});
this.formGroup.statusChanges.subscribe((formStatus) => {
console.log('Form Status: ', formStatus);
});
this.formGroup.controls['email'].statusChanges.subscribe((emailStatus) => {
console.log('Email Status: ', emailStatus);
});
}
ngOnDestroy(): void {
// Terminating the worker after we are done with it.
this.worker.terminate();
}
}
<form [formGroup]="formGroup" #ngForm="ngForm">
<input
formControlName="email"
[class.invalid]="formGroup.controls['email'].invalid && ngForm.submitted"
[class.valid]="formGroup.controls['email'].valid && ngForm.submitted"
/>
<button type="submit">Submit</button>
</form>
Upvotes: 0
Reputation: 761
If you're using Angular reactive form then you don't need to write regex for email.
1.Import Validators class
import { FormBuilder, Validators } from '@angular/forms'
this.fBuilder.group({
email: [null, [Validators.required, Validators.email]],
});
Upvotes: 0