Unable to establish an angular asynchronous validator

After studying the documentation, I implemented an Angular async validator class as shown below:

import { Injectable } from '@angular/core';
import {
  AsyncValidator,
  AbstractControl,
  ValidationErrors,
} from '@angular/forms';
import { XService } from '../../pages/x/x.service';
import { Observable, of } from 'rxjs';
import { map, catchError } from 'rxjs/operators';

@Injectable()
export class UniqueXValidator implements AsyncValidator {
  constructor(private xService: XService) {}

  validate(ctrl: AbstractControl): Observable<ValidationErrors | null> {
    return this.xService.checkExists(ctrl.value).pipe(
      map(exists =>
        exists ? { uniqueX: true } : null,
      ),
      catchError(() => of(null)),
    );
  }
}

Next, when attempting to attach it programmatically to a form control, I used the following code:

this.form.controls['code'].setAsyncValidators(
  UniqueXValidator,
);

A tooltip error message appeared in VS Code when hovering over "UniqueXValidator" in the previous code snippet. It stated:

Argument of type 'typeof UniqueXValidator' is not assignable to parameter of type 'AsyncValidatorFn | AsyncValidatorFn[]'.
Type 'typeof UniqueXValidator' is missing the following properties from type 'AsyncValidatorFn[]': pop, push, concat, join, and 25 more.ts(2345)

UPDATE: This issue may have been caused by a compatibility mismatch between my Angular version (7) and the version referenced in the documentation (11).

Answer №1

To enhance your validation process, consider using AsyncValidatorFn in place of AsyncValidator as shown below:

updatedUsernameValidator(): AsyncValidatorFn {
  return (control: AbstractControl): Observable<ValidationErrors | null> => {
    return this.checkIfUsernameUpdated(control.value).pipe(
      map(res => {
        // if res is true, username has been updated, return true
        return res ? { usernameUpdated: true } : null;
        // Note: Return null if there are no errors
      })
    );
  };
}

You can then include the validator during initialization:

this.fb.group({
  username: [
    null, [Validators.required],  [this.usernameService.updatedUsernameValidator()]
  ]
});

Alternatively, you can add the async validator at runtime:

this.form.controls['username'].setAsyncValidators(
  this.usernameService.updatedUsernameValidator()
);

Answer №2

setAsyncValidators requires an array of validators instead of a single one

Additionally, you do not require @Injectable() on the UniqueXValidator

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

Dropdownlist's onchange() event is no longer triggered when it is disabled

My current project at work involves working on an ASP.NET MVC application. My browser of choice is Internet Explorer, although I can't recall the exact version, and my work machine runs on 32-bit Windows 7. Within one of the view pages, there is a dr ...

Encountering an issue with TypeScript after applying a wrapper to a Material-UI button - specifically, the error message states that the type '{ children: string; color: "light-green"; }' is lacking certain properties

I'm currently working on creating wrapped components using MUI (@material-tailwind/react) within the environment of Next.js 14. However, I've run into a typescript error specifically in the MaterialButton component. Type '{ children: string; ...

Unable to locate the term "module"

I've been working on a TypeScript file that includes an exported function called sum: This script is meant to be run in Node.js. function sum(a:number):number{ return a; } module.exports.sum=sum; I'm encountering some issues and I'm not ...

Steps to automatically set a selected item when the page is loaded for the first time

I am currently working on a test project using Angular where I have to choose a branch, and once selected, graphics will load with the specific information related to that branch. However, when the page initially loads, I encounter an issue where the selec ...

Unable to retrieve information from a Node.js server using Angular 2

I am currently learning Angular 2 and attempting to retrieve data from a Node server using Angular 2 services. In my Angular component, I have a button. Upon clicking this button, the Angular service should send a request to the server and store the respo ...

Angular Batch Email UI Design Delivery

Looking to develop a user interface design resembling the process of sending batch emails. Are there any Angular libraries that can help create a UI similar to the one shown in this image? https://i.sstatic.net/cRvGx.jpg ...

"Dealing with an unspecified number of fields in an ExtJS data model

I have a data model that is designed to accommodate various incoming data by keeping it generic and allowing for the addition of multiple meta data tags to my project. How can I effectively map these data fields to the Model or access them in the array w ...

Save the selected value from the dropdown menu and automatically check the corresponding checkbox when it

I'm attempting to update the 'value' of a checkbox once an item is chosen from a dropdown list and then the checkbox itself is clicked. I have created a jQuery function that captures the value from the dropdown list (I omitted the code for t ...

Can Angular access a JSON file post-build?

Currently, I am developing an Angular 7 project that has to be deployed on various servers. One of the requirements is to retrieve the server URL from an environment file rather than hardcoding it as a static variable. I attempted to read the information ...

Unable to load dynamic data in Angular 2 smart table

Currently, I am utilizing Angular 6 along with smart table by visiting this link: . Everything was functioning smoothly, until the moment I attempted to switch from static to dynamic data: The following code works perfectly and displays all the content ...

Provide a dictionary-style object parameter that contains properties of type T to the class<T>

My approach involves using the concept of inheritance to initialize properties of a class<T> with an Object that implements all T properties passed to the constructor export default abstract class DatabaseObjectModel<T> extends JSONModel<T&g ...

Can a Promise be added to an Array later using Promise.all()?

While diving into a project, I pondered whether it is possible to initiate the Promise.all function in JavaScript and have it continue adding more Promises to the array while also running the existing ones. Quite an intriguing question! ...

Prevent TypeScript from generalizing string literals as types

I have a constant Object called STUDY_TAGS with specific properties const STUDY_TAGS ={ InstanceAvailability: { tag: "00080056", type: "optional", vr: "string" }, ModalitiesinStudy: { tag: "00080061", type: " ...

Exploring the depths of recursion with jQuery: Unraveling the

Having some issues with a recursive function in jQuery that's throwing an exception: 'Uncaught RangeError: Maximum call stack size exceeded' I can't figure out why this recursive function might be running infinitely. Any help would be ...

Tips on specifying a default value when receiving data from an API

I am working with a dropdown list that is populated from an API call. Here is my code snippet: <label>User Code:</label> <select ng-options="c as c.User for c in userList" ng-model="selectedUser" id="search3"> </select> To fet ...

How can I display a badge in my app when it is running using React Native?

For the past week, I've been dealing with an issue. My question is how can I display a new message badge without having to click on the message room when running my app. The badge should only show up after clicking on the message room. I see the badg ...

A guide on implementing a TypoError in Node.Js and Discord.Js for enabling a bot to enter a voice channel

Hello there, I'm currently working on a music Bot for Discord using Javascript with Node.Js and I've encountered an issue: This problem arises specifically with the "play" command, but it seems to occur with all commands that involve joining a v ...

Using JavaScript to delete a class from an HTML element

For the past 48 hours, I've been grappling with the challenge of removing an added class from an Element. Despite scouring the internet for a solution, I haven't been able to find one. I have successfully added a class to the navigation to displ ...

jquery select2 not functioning properly following ajax call

I am having an issue with my select2 control on the website. Initially, everything works perfectly fine when the site loads. However, if the content of the div named "simpleDiv" where the Select2 is located, is loaded via Ajax, the Select2 fails to display ...

Unable to locate module within the ngModule imports

I am facing a peculiar issue. I have used npm install to add ng-push, imported PushNotificationsModule from 'ng-push', and included PushNotificationsModule in my ngModule imports. Interestingly, both the ng build and ng build --prod commands are ...