Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular Custom Async Validator returning {__zone_symbol__state: null, __zone_symbol__value: Array(0)}

Am trying to implement custom validators. The non-async one (cannotContainSpaces) works just fine. The async one (shouldBeUnique), which, yes, is trivial at the moment, should be returning promise as I understand, which the Validator object should resolve. It doesn't. The errors collection on the formControl username shows this in the console:

{__zone_symbol__state: null, __zone_symbol__value: Array(0)}

Form component:

import { CustomValidators } from './custom.validators';
import { Component, Input } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';

@Component({
  selector: 'signup-form',
  templateUrl: './signup-form.component.html',
  styleUrls: ['./signup-form.component.css']
})
export class SignupFormComponent {

  form = new FormGroup({
    username: new FormControl('', [ 
       CustomValidators.cannotContainSpaces,
       CustomValidators.shouldBeUnique
      //  Validators.email, 
    ]),
    password: new FormControl('', Validators.required)
  })

  get username() {
    return this.form.get('username');
  }

  keyPressed(){
    console.log(this.username.errors)
  }

}

Custom validator method:

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

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

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

Relevant HTML:

<form [formGroup]="form">
    <div class="form-group">
        <label for="username">Username</label>
        <input 
            (keyup) = "keyPressed()" (blur) = "keyPressed()"
            formControlName="username"
            id="username" 
            type="text" 
            class="form-control">
        <div *ngIf="username.touched && username.invalid" class="alert alert-danger">
            <div *ngIf="username.errors.cannotContainSpaces">Username must not contain spaces</div>
            <div *ngIf="username.errors.shouldBeUnique">Sorry, that username has been taken</div>
        </div>
    </div>
like image 258
PakiPat Avatar asked Oct 26 '17 02:10

PakiPat


People also ask

How to use asyncvalidatorfn in formcontrol in angular?

Angular provides AsyncValidatorFn interface to create custom async validator function that will be used by FormControl in reactive form. Find the structure of AsyncValidatorFn interface from Angular doc. AsyncValidatorFn has a method declaration that has argument as AbstractControl and it will contain latest value of the form control.

What is async validator directive in ngmodel?

Async validator directive is used with ngModel in template-driven from. Async validator is used to validate data against the data located at remote server. To avoid frequent hit to server we should also use synchronous (sync) validators such as required, email, minlength and maxlength etc.

What is the use of ng_async_validators?

The NG_ASYNC_VALIDATORS is used as provider with multi: true in our async validator directive. Async validator directive is used in HTML template in reactive form or with ngModel in template-driven from. Async validator is used to validate data against the data located at remote server.

How do you implement asynchronous validation?

certain validators can need to perform an asynchronous operation, like calling a backend or a promise-based library. This can be implemented by having the validator return either a promise or an observable For validation to work properly, it's usually necessary to fine-tune exactly when the validators of a field are triggered.


1 Answers

Async validators are to be set as the third argument:

username: ['', [sync validators here], [async validators here]]

so change the the following:

username: new FormControl('', 
  [ 
   CustomValidators.cannotContainSpaces,
   CustomValidators.shouldBeUnique
  ]),

to:

username: new FormControl('', 
   [CustomValidators.cannotContainSpaces],
   [CustomValidators.shouldBeUnique]
),

DEMO: http://plnkr.co/edit/OceHbSl3atPHdcvNRQDs?p=preview

like image 133
AT82 Avatar answered Nov 03 '22 10:11

AT82