Encountering an undefined property error when trying to access 'userService' while implementing an async validator in Angular 12

For the past few days, I've been struggling to implement async validation with no success from various tutorials and solutions!

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

As I type in the input field, every keystroke prints the value, but then reports value is undefined!

What could be causing this error? How can it be resolved to ensure proper functioning of the async validator?

Any assistance in tackling this issue would be greatly appreciated.

Answer №1

It's actually quite simple:

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

(*)I assume that your service returns null if there are no duplicates

Check out this stackblitz to see it in action (try entering "fool" as a repeat)

If you're using Angular 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 already exists
    </mat-error>
    <mat-hint *ngIf="form.get('userId')?.pending">Validating...</mat-hint>
  </mat-form-field>

It's important to check errors on blur (otherwise the error may not be displayed by default in Angular Material, as the error is only shown if the form control is touched (edited and blurred))

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

Answer №2

I was able to replicate the issue using the provided stackblitz example

The issue arises from the fact that this in this scenario does not reference the class

An easy fix is to utilize arrow functions for the validate method

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;
          }))
        )
      );
  }

Check out the updated code Here

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

unable to retrieve data from HTML element

Having trouble accessing the value inside an HTML tag? Here's my dilemma: I can grab the entire tag, but not the value inside. In my app.component.html file: <p #docTitle>the thing I want to extract</p> And in my app.component.ts file: ...

Certain functionalities of Bootstrap may not be functioning properly within an Angular 6 project

I followed a tutorial from a source to integrate bootstrap into my newly developed angular 6 project. After compiling, I encountered no errors either in the 'ng console' or in the browser's developer tools. Although the buttons are well-co ...

No response was forthcoming

I have been trying to send a post request to my login endpoint, but I am not receiving any response. Despite thoroughly checking my code, I am unable to figure out why there is no response being sent back. My backend is built using Express in TypeScript. B ...

Software designed for the web that utilizes both frontend and backend technologies, including JavaScript

Currently, I am collaborating on a project for a company that created software using Delphi. The software primarily featured a minimalist browser as its central component. This browser was used to analyze webpages, recognize patterns, save data, and more. ...

The object's key values were unexpectedly empty despite containing data

There's an issue with my object - it initially gets key values, but then suddenly loses them all. All the key values become empty and a message appears in the console for the object: "this value was evaluated upon first expanding. it may have ch ...

How can I display two slides at once in Ionic 2/3 on a wide screen?

I have been searching for a solution that will allow me to display 1 ion-slide if the device screen is small, but if it's larger, then I want to display 2 ion-slides. Unfortunately, I have not been able to find a suitable solution yet. As an example, ...

An exploration of navigating through a generic interface in Angular

I've recently started exploring Angular and I'm trying to incorporate a generic interface to reuse pagination models from different sources. Let me share some code examples to clarify. export interface IUser{ id: string; name: string; email: stri ...

Enhance the performance of page loading and implement a consistent spinner feature to ensure smooth transitions for users in Next.js version 13

I am currently working on a project using Next.js 13, and I am encountering issues with slow loading times and an unstable spinner when navigating between pages. Specifically, when transitioning from the home page to the /example page, the experience is n ...

Protractor fails to capture the presence of mat-dialog-container

My Protractor test for an Angular 5 application is functioning well, except when it has to handle a popup containing input fields. The HTML element representing the popup looks like this: <mat-dialog-container class="mat-dialog-container ng-tns-c26-5 n ...

The ngTemplateOutletContext context source is not defined

That snippet of code was functional with Angular 2, and possibly even with versions earlier than Angular 4.3.6. Currently, the gradingKey object is undefined within the display or edit template section. However, it is not undefined in the getTemplate(gra ...

Error in AngularX TS: Trying to invoke a type that does not have a callable signature

Encountering an issue while working on a component, specifically during ng serve/build process. Please note that this error is different from any console errors, despite what some may think. The expected outcome is for the code to successfully build and ru ...

The reactivity of arrays in Vue components' props is limited

I've got an array with component data that I'm attempting to render using v-for <div :style="style" class="editor-component" v-for="(component, index) in components"> <Component :is="component.name" v-bind="component.o ...

Best practices for authenticating methods with Google signin in Angular projects

I have made significant progress towards getting the Google signin feature to work, reaching 95% completion. However, I am currently facing two issues with the code. Here is a simplified version of my current implementation: loginWithGoogle(): void { //t ...

How to Implement checked radio buttons in Angular 2 using ngModel

When generating radio buttons in Angular, I am using the following code: <div class="radio" *ngFor="let gender of genders"> <input type="radio" name="gender" [checked]="gender=='male'" [value]="gender"> {{gender}} </div> ...

Creating a unique theme export from a custom UI library with Material-UI

Currently, I am in the process of developing a unique UI library at my workplace which utilizes Material-UI. This UI library features a custom theme where I have integrated custom company colors into the palette object. While these custom colors work perfe ...

Ways to leverage Composite API in place of Mixin or Extends functionality

Currently, I am exploring the use of Vue3 for my project. One issue I am facing is that I need to create multiple components (SFC) with similar properties. I want to define these common properties using the composite API across all components, like so: con ...

Make the angular component refresh when the back button is pressed

I am working on a TeamSeasonComponent with the URL http://localhost:4200/teams/season/<team_id>. On this page, there are links to other team's pages which would take me to http://localhost:4200/teams/season/team_2_id>. I switch between these ...

Is it possible to use an if-else statement for both IP validation and URL validation?

Revise. I'm facing some issues with my code and I'm not sure why. I've added the 'FILTER_FLAG_NO_PRIV_RANGE' flag and also included a check to see if 'localhost' was entered. However, despite these efforts, it doesn&apos ...

Single sign-on (SSO) functionality experiencing issues when attempting to embed a Tableau link within an iframe

I have developed an application using Angular 4 and I am attempting to embed Tableau dashboards within the application. The embedded Tableau dashboard is asking for sign-in credentials. <iframe src="https://tableauserver/view/dashboard/12345" sandbox= ...

Angular 4: The parameter 'typeof CLASS' cannot be assigned to the parameter 'INTERFACE'

Exploring dynamic components in Angular has been quite interesting for me. However, I've encountered a roadblock that I'm unsure how to overcome. This is the interface I am working with: export interface InjectableComponent{ setData(data: a ...