Home > other >  Cannot read property 'userService' of undefined - implementing async validator (Angular 12
Cannot read property 'userService' of undefined - implementing async validator (Angular 12

Time:09-17

I've been trying to implement async validation for last few days. But none of the tutorials/solutions are working!

Service code-

getUserIdToCheckDuplicate(userId:any):Observable<any>{
    const url = ``; //url goes here
    return this.http.get<any>(url);
  }

Component code-

ngOnInit(): void {
 this.form = this.fb.group({
      userId: ['', [Validators.required],[this.validate]]})
}
validate(control: AbstractControl): Observable<ValidationErrors | null> {
    console.log(control.value);
    return of(control.value)
      .pipe(
        delay(10),
        switchMap((value) =>
          this.userService.getUserIdToCheckDuplicate(value).pipe(map(x => {
            return x.exists ? { exists: true } : null;
          }))
        )
      );
  }

Html code-

        <mat-form-field appearance="outline" fxFlex="1 1 calc(25% - 10px)" fxFlex.lt-md="1 1 calc(25% - 10px)"
                    fxFlex.lt-sm="100%" fxFlex.xs="100%" class="from-color" *ngIf="!data">
          <mat-label class="label-padding">User ID</mat-label>
             <input class="label-padding" formControlName="userId" matInput placeholder="User ID" required />
                <div style="color: red; font-weight: bold;" *ngIf="userId.errors?.exists">Already
                      Exists !</div>
     </mat-form-field>

In the console- console error

In the console, while I write something in the input, with every key storke it prints the value, but after that tells that value is undefined!

What is the reason behind this error? And how can I solve this? It should work properly so that the async validator works fine as well.

Can anyone help me with this please?

CodePudding user response:

I have managed to reproduce the error in the below stackblitz

The problem is that this in this context does not refer to the class

A simple solution is to simply use arrow function for validate

validate = (control: AbstractControl): Observable<ValidationErrors | null> => {
    console.log(control.value);
    return of(control.value)
      .pipe(
        delay(10),
        switchMap((value) =>
          this.userService.getUserIdToCheckDuplicate(value).pipe(map(x => {
            return x.exists ? { exists: true } : null;
          }))
        )
      );
  }

See this Here

CodePudding user response:

it's more simple than all this:

validate = (
    control: AbstractControl
  ): Observable<ValidationErrors | null> => {
    return this.userService.getUserIdToCheckDuplicate(control.value).pipe(
          map(x => {
            return x? { exists: true } : null;
          })
      
    );

(*)I suppose that your service return null if there're no duplicate

see stackblitz (to check, "fool" is repeat)

If you're using material

  <mat-form-field class="name" appearance="outline">
    <input matInput placeholder="Name" formControlName="userId">
    <mat-error *ngIf="form.get('userId')?.hasError('required')">
      Name is required*
    </mat-error>
    <mat-error *ngIf="form.get('userId')?.hasError('exists')">
      Name repeat
    </mat-error>
    <mat-hint *ngIf="form.get('userId')?.pending">Validating...</mat-hint>
  </mat-form-field>

But it's good that check errors 'onblur' (else the error is not showed by defect: in material, if we not use a custom error matcher, the error only is showed if the formControl is touched (edit and blur)

this.form = this.fb.group({
  userId: ['', [Validators.required], [this.validate]]
},{updateOn:'blur'});
  • Related