Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does my Async custom validator in Angular app works with typed input but not with pasted input?

I have created a custom validator that checks whether an email already exists in MySQL database. It works in that when a user types in an email that already exists in a database, an appropriate warning message will appear and not allow the admin to insert an existing user.

However, after testing it a few times, it looks like this validation can be easily broken by simply copying the email address from the database and pasting it in the form field. It is worth to note that when pasting in the email the first time round, it doesnt validate the email but when I then delete it and paste it in the second time, it then recognises it. I have shown the process in the attached photos below:

First input

Second input Please also see my code:

My custom validator:

import { Directive } from '@angular/core';
import { AsyncValidator, AbstractControl, ValidationErrors, NG_ASYNC_VALIDATORS, AsyncValidatorFn } from '@angular/forms';
import { Observable } from 'rxjs';
import { PatientsService } from './patients.service';
import { map } from 'rxjs/operators';

export function uniqueUsernameValidator(patientService: PatientsService): AsyncValidatorFn {
    return (c: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> => {
        return patientService.checkUserEmail(c.value).pipe(
            map(users => {
                return users && users.length > 0 ? { 'uniqueUsername': true } : null;
            })
        );
    };
}




@Directive({
    selector: '[uniqueUsername]',
    providers: [{ provide: NG_ASYNC_VALIDATORS, useExisting: UniqueUsernameValidatorDirective, multi: true }]
})
export class UniqueUsernameValidatorDirective implements AsyncValidator {

    constructor(private patientService: PatientsService) { }

    validate(c: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> {
        return uniqueUsernameValidator(this.patientService)(c);
    }

}

component I am using it in:

email: [
        null,
        [Validators.required,Validators.maxLength(30),Validators.email],
        [this.usernameService.usernameValidator()]
      ]

Referenced in my html

  <div class="form-group col-md-6">

    <label for="inputemail"id="label">Email</label>
    <input type="email" formControlName="email" name="email" class="form-control" id="inputEmail4"placeholder="Email">
    <div class="alert alert-danger" *ngIf="addForm.get('email').hasError('maxlength') && addForm.get('email').touched">
        Please enter maximum 30 characters.
       </div>
    <div class="alert alert-danger" *ngIf="addForm.get('email').hasError('required') && addForm.get('email').touched">
        Please enter an email address.
       </div>
       <div class="alert alert-danger"*ngIf="addForm.get('email').hasError('email') &&  addForm.get('email').touched">
        Please insert a valid email address.
      </div>

      <!--If same email exists...-->
      <div class="alert alert-danger"*ngIf=" addForm.controls['email']?.errors?.emailExists">
        Email already exists
      </div>
  </div>

Could someone please advise ? I am trying for it to also validate clipboard events (copy and paste) the first time round.

like image 373
KeenLearnerA Avatar asked Aug 11 '20 12:08

KeenLearnerA


People also ask

What is the difference between synchronous and asynchronous Validators in Angular?

Synchronous and asynchronous Validators are very similar - the main difference is that a sync Validator returns an error object instance directly, while the async version returns an Observable of the the same object. The most common use case for async Validators is doing a server validation via an HTTP Callback.


1 Answers

try this :

onPasteEmail(): void {
  addForm.updateValueAndValidity();
}
<input (paste)="onPasteEmail()">

paste event will be trigger when you copy&paste your email the first time, then updateValueAndValidity() function from reactive form will trigger your validation

like image 69
Gauthier T. Avatar answered Oct 12 '22 02:10

Gauthier T.