Issue with custom validator in Angular 6: setTimeout function not functioning as expected

Currently, I am in the process of following a tutorial to implement Asynchronous validation in Angular. The goal is to create a custom validator named shouldBeUnique that will be triggered after a 2-second delay. To achieve this, I have utilized the setTimeout function within the validator. However, I am facing an issue where the error message is not being displayed in the designated div.

Below is my custom validation error file:

import { AbstractControl, ValidationErrors } from '@angular/forms';

export class UsernameValidator {
   static cannotContainSpace(control: AbstractControl): ValidationErrors | null {
        if ((control.value as string).indexOf(' ') >= 0) {
            return { cannotContainSpace: true };
        }
        return null;
    }

static shouldBeUnique(control: AbstractControl): Promise<ValidationErrors | null> {
         return new Promise((resolve, reject) => {
             setTimeout(() => {
                 if (control.value === 'bilal') {
                     resolve({shouldBeUnique: true});
                 } else {
                     resolve(null);
                 }
             }, 2000);
         });
     }
}

Here is the HTML file snippet:

<form [formGroup] = "form">
    <div class="form-group">
        <label for="username">Username</label>
        <input 
            formControlName = "username"
            id="username" 
            type="text" 
            class="form-control">
        <div *ngIf="username.touched && username.invalid" class="alert alert-danger">
            <div *ngIf="username.errors.required">Username is required</div>
            <div *ngIf="username.errors.minlength">
                Minimum length of {{username.errors.minlength.requiredLength}} characters is required
            </div>
            <div *ngIf="username.errors.cannotContainSpace">
                Username cannot contain spaces
            </div>
            <div *ngIf="username.errors.shouldBeUnique">
                    Username must be unique
                </div>
        </div>    
    </div>
    <div class="form-group">
        <label for="password">Password</label>
        <input 
            formControlName = "password"
            id="password" 
            type="text" 
            class="form-control">
    </div>
    <button class="btn btn-primary" type="submit">Sign Up</button>
</form>

Lastly, here is the TypeScript file:

import { Component } from '@angular/core';
import {FormGroup, FormControl, Validators} from '@angular/forms';
import { UsernameValidator } from './username.validator';
@Component({
  // tslint:disable-next-line:component-selector
  selector: 'signup-form',
  templateUrl: './signup-form.component.html',
  styleUrls: ['./signup-form.component.css']
})
export class SignupFormComponent {

  form = new FormGroup({
    username: new FormControl('', [
      Validators.required,
      Validators.minLength(3),
      UsernameValidator.cannotContainSpace,
      UsernameValidator.shouldBeUnique
    ]),
    password: new FormControl('' , Validators.required)
  });
  get username() {
    return this.form.get('username');
  }

}

Answer №1

It's important to remember that async validators need to be the third argument when initializing a FormControl. Here is an example of how you should set it up:

form = new FormGroup({
    username: new FormControl('', 
    [
      // regular validators
      Validators.required,
      Validators.minLength(3),
      UsernameValidator.cannotContainSpace
    ], 
    [
      // async validators
      UsernameValidator.shouldBeUnique
    ]),
    password: new FormControl('' , Validators.required)
  });

Answer №2

Validators that are asynchronous should be placed after synchronous validators.

export declare class FormControl extends AbstractControl {
  constructor(
    formState?: any,
    validatorOrOpts?: ValidatorFn | ValidatorFn[] | AbstractControlOptions | null, 
    asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[] | null
);

new FormGroup({
    username: new FormControl('', 
    [
      Validators.required,
      Validators.minLength(3),
      UsernameValidator.shouldBeUnique
    ], 
    [
     UsernameValidator.cannotContainSpace,
    ])
  });

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

Using the PUT method in combination with express and sequelize

I am having trouble using the PUT method to update data based on req.params.id. My approach involves retrieving data by id, displaying it in a table format, allowing users to make changes, and then updating the database with the new values. Here is the co ...

Guide on making a prev/next | first/last button functional in list.js pagination

Is there a way to enhance my paginated index by adding prev/next, first/last buttons? I am curious if anyone has implemented these features using List.js. <script src='//cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js&ap ...

This jQuery ajax request is returning a readyState of 1 or an incorrect data type

I am currently troubleshooting an issue with the ajax response in my Wordpress plugin script. Whenever I try to retrieve a json file using jQuery.ajax, I receive {readyState: 1} as the result. Even when setting async: false, the response is always plain te ...

What is the most effective way to inform the user when the nodeJS server can be accessed through socketIO?

I have developed a web app that indicates to the user when the server is online for data submission. Although the current code functions properly for single-user interaction, I am facing an issue where one user's connection or disconnection directly i ...

Utilizing jQuery to enable a div to follow the touchmove or mousemove events while also automatically

I am looking to create a basic function in my jQuery script. I want the pages to slide horizontally in response to the movement of a finger or cursor on the screen. While there are many plugins available for this purpose, I prefer a simple, customized solu ...

What are some ways to enhance the functionality of the initComplete feature in Dat

$('#example').dataTable( { "initComplete": function(settings, json) { alert( 'DataTables has finished its initialisation.' ); } } ); Is there a way to extend the initComplete function for other languages? $.extend( true, $.f ...

How to implement tree selection feature in Angular PrimeNG version 11.x on a tree component

I am currently working with primeng v11.x and utilizing p-tree to showcase hierarchy view with checkboxes. However, I would like to have this displayed within a dropdown similar to p-treeselect. Due to constraints, I am unable to upgrade primeng at the mom ...

Retrieving checkbox value upon form submission

Imagine having a form containing several checkboxes. Upon submitting the form, you aim to display all values of the selected checkboxes. <form> <input type="checkbox" id="product1" name="product1" value="12"> <input type="checkbox" id="prod ...

display a div positioned relatively next to another div

I'm having trouble displaying a textbox next to another div on my webpage. Instead of appearing next to the div, it is showing up below it. The textbox needs to have an absolute position. You can see the issue in action by checking out this demo. Than ...

"Organizing Your Content: A Guide to Grouping Information under Specific

How can I organize content under different headings? I am using two methods to retrieve data: 1. axios.get('/api/get/headers') 2. axios.get('api/get/contents') I am struggling with how to properly structure this, especially since the ...

Choosing a lone column in amcharts 4

Is there a way to highlight just one column and unhighlight any previously highlighted columns in an amCharts 4 Column chart? I've been attempting to adjust the colors of all the columns before highlighting the target column, but it doesn't seem ...

Updating a Div on your webpage using a JQuery UI dialog: A step-by-step guide

I am currently trying to update my webpage from a JQuery UI dialog, but the code I have so far does not seem to be working. Any assistance or guidance would be greatly appreciated. function submit_new_site() { // These are the input text IDs on the ...

Fixing perspective clipping in Three.js

In my Three.js project, I have a plane inside a sphere that I am applying a shader to in order to achieve certain visual effects on the sphere. To ensure that the plane is always facing the camera, I am using the lookAt method. However, I have noticed that ...

Using template variable in Angular5 to create a dependant dropdown feature

I have a component where I am subscribing to an observable that contains nested levels of JSON objects. How can I create multiple dropdown selects that depend on the previous selection? I am using template variables to reference the selects. this._exposu ...

AJAX request: No values are being returned by $_GET

After spending hours trying to figure this out... I've been working on using AJAX to grab values from a jQuery slider within an <input> tag. The AJAX request is not failing (see code below), and when I use console.log to check the variable I&ap ...

Textbox textchange event triggers Javascript function when Checked=True

$('.LblQTY').on('input', function () { var currentRow = $(this).closest('tr'); var rate = parseFloat(currentRow.find('.LblRate').text()); var quantity = parseFloat($(this).val() == '' ? '0& ...

Experimenting with an Angular 2 component using a simulated service

Currently, I am experimenting with testing an Angular2 component that relies on a service. In order to conduct the test effectively, I aim to provide a stubbed service. However, it appears that the test component does not recognize this stubbed service. ...

I'm struggling to include a link in my project card component - I've tried using both the Link tag and anchor tag, but so far, I haven't been successful in

I am having trouble getting the link tag to work properly in my UI. I have tried using both the link and anchor tags, but neither seems to be functioning as expected. Can someone please advise on how to fix this issue? https://i.sstatic.net/tAD7C.png I w ...

Maintain the specific type based on the provided data, rather than the default value, when a related generic is defined

When it comes to unit tests, I prefer a more flexible approach with dynamic generic types that eliminate the need for type casting. I want T to be open-ended, but if I specify a type, I expect to receive an exact match. For R, I need it to precisely matc ...

The debate between ensuring input validity and making fields mandatory on multi-page forms

I am currently working on a multi-page form and using jQuery Validate to validate it. The user has four options: next, prev, save, submit. Save, next, and prev all save the current page within the form; whereas submit is similar to save, but triggers addi ...