The issue of the Angular service being consistently undefined arises when it is invoked within an

I have already researched numerous other SO questions, but none of the solutions worked for me.

My goal is to implement an async validator that checks if a entered username already exists. However, every time I type a letter into the input field, I encounter an error stating that my userService instance is undefined.

Here is my implementation of UserService:

export interface UsernameCheck {
  info: string,
  usernameAvailable: boolean;
}

@Injectable({
  providedIn: 'root'
})
export class UserService {
  private apiUrl = 'http://localhost:5001/project-f-angular/us-central1';

  constructor(
    private http: HttpClient
  ) { }

  checkUsername(username: string) {
    const params = new HttpParams().set('username', username);

    return this.http.get<UsernameCheck>(`${this.apiUrl}/checkUsername`, {params});
  }
}

The HTTP request is connected to a locally running Firebase Cloud Functions emulator.

Below is the component where I am utilizing it:

export class SignUpComponent implements OnInit {
  signUpForm: FormGroup;

  constructor(
    private userService: UserService,
    private formBuilder: FormBuilder) {
  }

  ngOnInit() {
    this.signUpForm = this.formBuilder.group({
      username: [null, Validators.required, this.existingUsername],
      email: [null, [Validators.required, Validators.email]],
      password: [null, Validators.required],
      confirmPassword: [null, Validators.required]
    });
  }

  existingUsername(control: FormControl): Promise<any> | Observable<any> {
    console.log(control.value);
    return this.userService.checkUsername(control.value)
      .pipe(
        map(res => {
          return res.usernameAvailable ? null : {existingUsername: true};
        })
      );
  }
}

Upon entering the first letter in the input field, I encountered the following error:

ERROR TypeError: Cannot read property 'userService' of undefined
    at existingUsername (sign-up.component.ts:45)
    at forms.js:1492
    at Array.map (<anonymous>)
    at _executeAsyncValidators (forms.js:1488)
    at FormControl.asyncValidator (forms.js:1446)
    at FormControl._runAsyncValidator (forms.js:4100)
    at FormControl.updateValueAndValidity (forms.js:4053)
    at FormControl.setValue (forms.js:4692)
    at updateControl (forms.js:3299)
    at DefaultValueAccessor.onChange (forms.js:3271)

In addition, I included my service in app.module.ts under providers.

If I subscribe to my userService inside ngOnInit, my method works as expected and returns the correct response.

As I am new to reactive forms and validators, I would appreciate any insights on what I might be doing wrong.

Answer №1

To ensure the validator has the correct context, it is important to bind to this.

this.signUpForm = this.formBuilder.group({
   username: [null, Validators.required, this.existingUsername.bind(this)],  // <--
   email: [null, [Validators.required, Validators.email]],
   password: [null, Validators.required],
   confirmPassword: [null, Validators.required]
});

Check out this stackblitz example for a demonstration of the solution.

I hope this explanation helps you with your query.

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

Typescript: Dynamic return type determined by argument properties

I have a function that should return two different types based on its argument props. interface IPaginateParams { perPage: number; currentPage: number; isFromStart?: boolean; } interface IWithPagination<Data, TParams extends IPaginateParams = IPa ...

Guide on how to run functions in Angular 2+ directly from the console?

My application is designed to operate within a chromium browser using chromiumfx. With chromiumfx, you can seamlessly run any JavaScript functions as if you were working in a console environment. Here's a snippet of my code: import { Component } f ...

Triggering multiple updates within a single method in Angular will cause the effect or computed function to only be triggered

Upon entering the realm of signals, our team stumbled upon a peculiar issue. Picture a scenario where a component has an effect on a signal which is a public member. In the constructor of the component, certain logic is executed to update the signal value ...

How can time duration be accurately represented in TypeScript?

As I work on designing an interface for my personal project, I am in need of adding a field that represents the length of time taken to complete a task. What data type and format should I use in TypeScript to express this? Below is the interface I have cr ...

Ways to retrieve and upload a blob from a file object

After receiving a file object via an HTML input on-change event in my component.html: onFileSelected(event) { this.selectedFile = event.target.files[0]; } Now, I need to send a POST request to upload the image to the database. The database only acc ...

SSR routing with parameters in Angular Universal seems to be failing after intial navigation

I'm currently experiencing an issue with routing using path parameters: Navigation works perfectly when moving between categories initially, but once I navigate from one category to another, the routing doesn't update even though the URL in the ...

Experience the magic of live streaming with our cutting-edge technology bundle featuring RTSP streaming, AspNet 5 API integration, FFM

Description: I am working on an API (ASP.Net 5) that connects to an IP Camera through RTSP. The camera sends a h264 stream converted with ffmpeg as an m3u8 stream, which is then returned to the Angular client in the following manner: public async Task< ...

Obtain an Instance of a Class Using a Decorator

Delving deep into the world of decorators, I stumbled upon some fascinating ideas for incorporating them into my reflux implementation. My concept involves tagging a store's class method with an action, so that whenever that action is triggered, it au ...

Variations in default export behavior in Webpack when using Typescript versus Javascript

In my React application, I have a page that imports a component from another file. // Code snippet from IconPage.tsx import {AccountBalanceIcon} from './icons'; <AccountBalanceIcon /> // Code snippet from ./icons.ts export { default as A ...

The initial values of Typescript class members are merged directly into the class constructor

This issue has been well documented (check out Initializing variables inline during declaration vs in the constructor in Angular with TS on SO for reference), but it can lead to challenging memory problems. Take a look at the example below class Bar { ...

Navigating with nginx

My Angular2 application works perfectly fine when using the local webpack dev server. However, after deploying the application on a server behind nginx, I am facing an issue. I can navigate using application links, but if I enter a URL directly into the br ...

When you use map to transform the value, Observable will consistently return as undefined

Can anyone help me figure out why, when I transform the observable, it returns undefined in the console log even though there are assigned values? HTTP Request getLibraryCardPeople(bookName: String): Observable<people[]> { return this.http.get<Li ...

Why isn't the background-image displaying with the use of the url() function?

I've been attempting to set an image as the background using background-img:url(imageLing), but it's not working properly. When I inspect the element, it shows me background-image: url(assets/backgrounds/5.jpg);. What could be causing this issue? ...

The element 'Component' is not eligible to be utilized as a JSX component (typed layout)

I encountered a type error while working with the following code snippet: {getLayout(<Component {...pageProps} />)} The error message states that 'Component' cannot be used as a JSX component. This is because its element type 'Compo ...

Unexpected behavior: ng2-dragula modelDrop event leading to undefined array

Struggling to figure out the issue with this code. As shown in this GIF, when dragging a div from one container to another, the object disappears and the array becomes undefined. https://i.stack.imgur.com/TELyc.gif Here is the code snippet: Main View.ht ...

Reacting to the dynamic removal of spaces

Is there a way to dynamically remove the space between removed chips and older chips in Material-UI when deleting one of them? <div className="row contactsContainer"> {contacts.map((contac ...

Obtain multiple class instances through HTTP-Get in Angular

Initially, explaining this with my actual code can be confusing, so I'll simplify the issue using a smaller example. Imagine my project retrieves data from 2 tables on the server, employeeDetails and employeeNames. employeeNames: This table consists ...

What is the significance of static constants?

In my TypeScript project, I'm working on creating a constants file that will provide an Opaque token object when ServiceConstants.AUTH_SERVICE_TOKEN is called. I've experimented with two approaches: Using ServiceConstants.ts as a namespace exp ...

TypeScript creates a .d.ts file that contains declaration statements rather than export declarations

When compiling my code using the command tsc --p typescript/tsconfig.json --outFile "dist/umd/index.d.ts", I encountered an issue. The contents of my tsconfig.json file are as follows: { "include": ["../src/**/*"], "exclude": ["../**/*.test.ts"], ...

Error encountered in lodash.js in Angular 2 framework

I have been attempting to implement lodash for a datatable. Here are the steps I followed: First, I tried running npm install lodash, but encountered an error stating that the package could not be found After researching the issue, I attempted npm in ...