Angular's custom validator consistently returns a null value

I need help with validating the uniqueness of a username field in a form where an administrator can create a new user. I have implemented a uniqueUserNameValidator function for this purpose, but it always returns null. I suspect that the issue lies in the fact that the service used is asynchronous. How can I ensure that the async operation completes before proceeding? Adding an await statement seems to cause strange problems. Any guidance on resolving this would be greatly appreciated.

Below is where the validator is supposed to be applied:

this.userService.getEmployeeById(this.employeeId).subscribe(result => {
        this.employee = result;
        this.employeeDetailForm = new FormGroup({
          userName: new FormControl(this.employee.userName, [Validators.required, this.uniqueUserNameValidator.bind(this)]) 
        });

Here is the uniqueUserNameValidator implementation:

      private uniqueUserNameValidator(control: FormControl): { [s: string]: boolean } {
    
        this.employee.userName = control.value;
        var userExists: boolean;
    
        this.userService.checkIfEmployeeUserNameExists(this.employee).subscribe(data => {
          userExists = data;
        })
    
        if (userExists) {
          return { userExists: true };
        }
        return null;
      }

And here is the relevant service method:

      checkIfEmployeeUserNameExists(employee: Employee) {
        return this.http.put<boolean>(this.baseUrl + 'employees/isUserNameUnique', employee)
      }

Answer №1

It has been mentioned by other users in the comments that utilizing an async validator is key to achieving the desired functionality. By passing validatorOrOpts as the second parameter when creating a new control, you gain more nuanced control over the validators that can be applied.

this.employeeDetailForm = new FormGroup({
  userName: new FormControl(this.employee.userName, {
    validators: [Validators.required],
    asyncValidators: [this.partnerCodeAvailabilityValidator.bind(this)]
  }) 
});

The structure of the partnerCodeAvailabilityValidator should resemble this:

private partnerCodeAvailabilityValidator(
  control: AbstractControl
): Observable<ValidationErrors | null> {
  this.employee.userName = control.value;
  return this.userService
    .checkIfEmployeeUserNameExists(this.employee)
    .pipe(map((data) => data ? ({ userExists: data }) : null));
}

If preferred, you also have the option to construct a directive and implement the AsyncValidator interface for use with template driven forms.

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

What other methods are available to verify null and assign a value?

Is there a more efficient approach for accomplishing this task? theTitle = responsesToUse[i]["Title"]; if(theTitle == null) theTitle = ""; ...

Tips for incorporating the observer design pattern in REST APIs (Communication between front-end and back-end)

Is it possible to subscribe once to an API and receive multiple responses until I unsubscribe from that event? If so, how can this be achieved? If not, why does this approach not align with the observer pattern's guidelines? I attempted using the yie ...

Using a Typescript-specific type within a switch case statement

I'm currently working on a function that, when given an enum value, should return a specific type. I am facing an issue where Typescript does not seem to recognize the properties inside switch and if statements. interface X { x: string; } interface ...

Struggling to integrate authentication and authorization features into a ReactJS application with Microsoft Azure AD or Database login functionality

We have an application built on React v18 with a backend that includes a Web API and SQL Server database. Our requirement is to authenticate and authorize users using either MS Azure AD or the database. If a user attempts to log in with a username and pas ...

Abort S3 file upload using ASW-SDK

Is there a way to abort an upload without raising an error Upload aborted. when calling upload.abort()? import { PutObjectCommandInput, S3Client } from '@aws-sdk/client-s3'; import { Progress, Upload } from "@aws-sdk/lib-storage"; cons ...

Derive the property type based on the type of another property in TypeScript

interface customFeatureType<Properties=any, State=any> { defaultState: State; properties: Properties; analyzeState: (properties: Properties, state: State) => any; } const customFeatureComponent: customFeatureType = { defaultState: { lastN ...

Utilizing headers in apollo watchQuery results in undefined data

Utilizing the apollo-angular package for querying our backend using graphQL has been smooth sailing. However, things take a turn when I attempt to include headers in the query. I am specifically adding a custom header to extract flattened data from the ba ...

Utilizing type guards in prop functions for conditional rendering within React TypeScript adds an extra layer

In my code, I am conditionally rendering a Button. However, I encountered an issue on line 7 where TypeScript is indicating that the first parameter of the exportExcel function may be null even though it should not be, considering the conditional render lo ...

How to implement automatic clicking using Material Angular components

Looking to incorporate layout tabs from Angular Material into my project: https://material.angular.io/components/tabs/overview Interested in implementing auto-click functionality - how can I instruct Angular to simulate clicking on the "Tab1" link, waiti ...

Determining the type relationship between two generic types when using a union

Here is the code snippet defining a React component using react-hook-form: import { type FieldPath, type FieldValues, type FieldPathValue, } from "react-hook-form"; interface FormControlRadioBoxProps< TFieldValues extends FieldValue ...

"Once the queryParams have been updated, the ActivatedRoute.queryParams event is triggered once

Within my Angular component, I am making an API call by passing a hash string extracted from the current query parameters. Upon receiving the API result, a new hash is also obtained and set as the new hash query parameter. Subsequently, the next API call w ...

The Unhandled Promise Rejection Warning in mocha and ts-node is due to a TypeError that arises when attempting to convert undefined or null values

I've been encountering issues while setting up ts-node with mocha, as the test script consistently fails. I attempted to run the following commands: mocha --require ts-node/register --extensions ts,tsx --watch --watch-files src 'src/**/*.spec.{ ...

Issue encountered during mozjpeg installation - unable to locate mozjpeg's cjpeg in the vendor directory due to

During my attempt to set up mozjpeg within a Docker container running NAME="Alpine Linux" ID=alpine VERSION_ID=3.11.7 PRETTY_NAME="Alpine Linux v3.11" HOME_URL="https://alpinelinux.org/" BUG_REPORT_URL="https://bugs.alpin ...

What is the source of the compiler options in tsconfig.json?

Currently utilizing Typescript in NestJs, I have incorporated various packages. However, the specific package responsible for altering these settings remains unknown to me: "checkJs": false, "skipLibCheck": true Is there a method to ...

How can one access a specific element by its id that is located within an ng-template in Angular 6?

I have a question regarding accessing a button element inside an ng-template tag using its id in the TypeScript file. How can I accomplish that without encountering undefined errors? This is what I have tried so far: HTML <ng-template #popup > ...

I have a data.json file with a URL that I need to access in my view using Angular. How can I achieve this without relying on innerHTML?

Here is the JSON file data.json that I am referring to: { "id": 1, "title": "POC", "desc": "<a href='www.google.com'>HOMEPAGE</a>", "status": "done", "percentage_finished": 100 } I am tryi ...

Sweetalert seems to have hit a roadblock and is not functioning properly. An error has been detected in its TS file

Currently, I am responsible for maintaining an application that utilizes Angular 7.0.7 and Node 10.20.1. Everything was running smoothly until yesterday when my PC unexpectedly restarted. Upon trying to run ng serve, I encountered the following error: E ...

Optimal strategies for managing server-side validation/errors in Angular applications

Back in the day, I used to retrieve HTTP responses with a TypeScript object. validateTokenHttp(token: string): Observable<User> { return this.http.get<User>(`${environment.api}/auth/verifyToken/${token}`); } Sometimes it would return a Us ...

What is the best way to utilize *ngFor for looping in Angular 6 in order to display three images simultaneously?

I have successfully added 3 images on a single slide. How can I implement *ngFor to dynamically load data? <carousel> <slide> <img src="../../assets/wts1.png" alt="first slide" style="display: inline-blo ...

The date displayed in the table is incorrectly showing 04 instead of 03 when using the pipe

{{element.createdAt | date: 'MM/dd/yyyy h:mm'}} why are the dates in the database all showing as 23 but some values are displaying as 24? Please confirm. The first two values created in the db show a createdAt time of 3, but the table is showing ...