0
votes

I get the error 'Expected validator to return Promise or Observable' while trying to implement an custom synchronous validator. I am using the FormControl and FormGroup classes for bulding the validators.

This change from beta to final release is confusing. Kindly help me out.

Thanks in Advance


Please find below my code for the same:

userNameValidator.ts

import { FormControl } from '@angular2/common';

export class UserNameValidator
{


  static cannotContainSpaces(control:Control)
  {
   const username = control.value;
   console.log(username + "here")

   console.log( username.indexOf(' ')>=0 ? {'containsSpace':true} : null);

   return username.indexOf(' ')>=0 ? {'containsSpace':true} : null;

 }
}


signup.component.ts

import { Component } from '@angular/core';
import { FormControl, FormGroup, Validators, FormBuilder} from '@angular/forms';
import { UserNameValidator } from './userNameValidator';


@Component({
  selector: 'my-app',
  templateUrl: './signup.component.html'
})

export class SignupComponent
{
  form: FormGroup;

  constructor(fb: FormBuilder)
  {
    this.form = fb.group({
    username: 
     [null,Validators.compose([Validators.required,Validators.minLength(4)]), 
     UserNameValidator.cannotContainSpaces],
    password: [null,Validators.compose([Validators.required])]
    })

  }


signup.component.html

<form [formGroup]="form" >
  <div class="form-group">
    <label for="username">Username: </label>
    <input
      class= "form-control"
      type="text"
      formControlName="username">

        <div *ngIf="username.touched && 
        form.controls['username'].getError('required')"
              class="alert alert-danger">Username cannot be empty
        </div>

        <div *ngIf="form.controls['username'].getError('minlength')" class = 
        "alert alert-danger">
              Username should have atlest 
              {{username.errors.minlength.requiredLength}} characters
        </div>

        <div
          *ngIf="form.controls.username.hasError('containsSpaces')"
          class="alert alert-danger" > Username Can't Contains Spaces</div>

  </div>
1
Haven't done this myself so not adding as an answer but might try making your function static cannotContainSpaces(control:Control):Promise and return a new Promise that wraps the value you want it to resolve to something like Promise.resolve(username.indexOf(' ')>=0 ? {'containsSpace':true} : null) - shaunhusain

1 Answers

0
votes

There're a lot of mistakes in your code...

1 - The import line:

The package @angular2/common just doesn't exists. It's @angular/common, but in your case, you want to get FormControl, which one resides in @angular/forms package.

should be:

import { FormControl } from '@angular/forms';

2 - The signature of method:

static cannotContainSpaces(control: Control) { ... }

should be:

static cannotContainSpaces(control: FormControl) { ... }

3 - The construction of form:

this.form = fb.group({
  username:[null, Validators.compose([Validators.required, Validators.minLength(4)]), 
 UserNameValidator.cannotContainSpaces],
  password: [null, Validators.compose([Validators.required])]
})

The code above means that the UsernameValidator is an async validator, but according to the title of question, you want it to be sync, so it must go together with the other validators (in the 2nd. parameter).

should be:

this.form = fb.group({
  username: [
    null, 
    Validators.compose([
      Validators.required, 
      Validators.minLength(4), 
      UserNameValidator.cannotContainSpaces
    ])
  ],
  password: [null, Validators.compose([Validators.required])]
});

Tip: You don't need to use Validators.compose, you can just pass an array (see PLUNKER below).

4 - In validator you're returning { containsSpace: true } (in singular), but in template, you're checking it in plural containsSpaces.

Also, there are minor errors in template, that are fixed in PLUNKER (see below).

Here's the PLUNKER working.