I am pretty sure this is something I have done wrong and could do with another pair of eyes to point out the no doubt obvious error in my code.
I have a component that is inside a mat-tab and is lazy loaded. In the component I have a field in a reactive form that is created as below.
I have defined an email validator pattern in environment.ts
export const environment = {
...
validators: {
// tslint:disable-next-line:max-line-length
email: /^(([^<>()\[\]\\.,;:\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,}))$/gi
}
}
The form is defined here in the component constructor:
this.form = this.fb.group({
...
'primary_contact': this.fb.group({
'name': [''],
'email': ['', { validators: [Validators.required, Validators.pattern(environment.validators.email)], updateOn: 'blur' }],
'phone': ['']
}),
...
});
And the form is populated in ngOnInit from an input variable:
@Input() tenant: Tenant;
ngOnInit() {
this.form.patchValue({
...this.tenant
});
this.form.updateValueAndValidity();
}
And finally in the template I have the following:
<div fxFlex fxLayout="row wrap" fxLayout.xs="column wrap" fxLayoutGap="24px grid" formGroupName="primary_contact”>
...
<div fxFlex="50">
<mat-form-field class="full-width">
<mat-label>Primary Contact Phone</mat-label>
<input matInput type="tel" formControlName="phone" />
</mat-form-field>
</div>
...
</div>
<mat-divider></mat-divider>
<div class="form-actions">
<button mat-flat-button color="primary" [disabled]="form.invalid" (click)="onSaveChanges()">Save changes</button>
<a mat-button [routerLink]="['../../']">Cancel</a>
</div>
Now to my problem, when the component loads the form can be either valid or invalid and switching between the two tabs the field will switch between a valid/invalid state.
Can anyone see what I am doing wrong please?
I have a stackblitz here which replicates the problem I am seeing.
Updated
So after taking a look at the Angular email validator and stripping my example back, I found the following which seems to indicate a problem with the regex itself. See the two snippets below, if you run them using my regex and the second one with the regex from the angular validators you get different results
Using regex from above
const re1 = new RegExp(/^(([^<>()\[\]\\.,;:\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,}))$/gi);
for (let i = 0; i < 10; i++) {
console.log(re1.test('test@gmail.com'));
}
Using regex from Angular email validator
const re2 = new RegExp(/^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+)*@[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])?)*$/);
for (let i = 0; i < 10; i++) {
console.log(re2.test('test@gmail.com'));
}
So to update the question, why does my regular expression test alternate between valid and invalid?