Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 6: setTimeout function is not working in my custom validator

I am following a tutorial in order to perform Asynchronous validation in Angular. What I am trying to achieve is my custom validator which is shouldBeUnique should be call after delay of 2 seconds. I am using setTimeout function in it but it is not working. even Error message not shows in div.

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

HTML file.

<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">
                minlength {{username.errors.minlength.requiredLength}} is required
            </div>
            <div *ngIf="username.errors.cannotContainSpace">
                cannot contain space
            </div>
            <div *ngIf="username.errors.shouldBeUnique">
                    username should b 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>

Type script 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');
  }

}
like image 721
billal Avatar asked Mar 06 '23 10:03

billal


2 Answers

Async validators should be the third argument to FormControl, so you should initialize yours like this:

form = new FormGroup({
    username: new FormControl('', 
    [
      // regular validators
      Validators.required,
      Validators.minLength(3),
      UsernameValidator.cannotContainSpace
    ], 
    [
      // async validators
      UsernameValidator.shouldBeUnique
    ]),
    password: new FormControl('' , Validators.required)
  });
like image 122
sloth Avatar answered Mar 07 '23 22:03

sloth


Async validators should be placed after 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,
    ])
  });
like image 22
Buggy Avatar answered Mar 07 '23 22:03

Buggy