5

I've got a sign up form and I want to check that if the username is already taken or not. To achieve this I'm using promises now. My sign up component looks like this:

import { Component, OnInit } from '@angular/core';
import { FormControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UserService } from '../shared/user.service'

@Component({
  selector: 'app-auth',
  providers: [],
  templateUrl: './auth.component.html',
  styleUrls: ['./auth.component.css']
})

export class AuthComponent implements OnInit {

  // Tabs for log in or sign up
  tab = 'signup';

  // Sign up form
  signUpForm: FormGroup;

  // Log in form
  logInForm: FormGroup;

  constructor(private formBuilder: FormBuilder, private ussr: UserService) {
     this.signUpForm = this.formBuilder.group({
       'username': [null, [
         Validators.required, Validators.minLength(4), Validators.maxLength(12), this.ussr.getUserNameFromServer
       ]], 
       'email': '', 
       'password': '' });
    this.logInForm = this.formBuilder.group({ 'username': '', 'password': '' });
  }

  ngOnInit() {
  }

  activeTab(tab: string) {
    this.tab = tab;
  }

  signUpSubmit(value: any) {
    console.log(value);
  }

}

And the UserService:

import { Injectable } from '@angular/core';
import { Http, Response, Headers, RequestOptions  } from '@angular/http';
import { FormControl } from '@angular/forms';
import 'rxjs/add/operator/map';

@Injectable()
export class UserService {

    constructor (private http: Http) {}

    private extractData (res: Response) {
        let body = res.json();
        return body || { };
    }

    getUserNameFromServer = (c: FormControl) => {

        return new Promise (
             (resolve, reject) => {
                 this.http.get('https://jsonplaceholder.typicode.com/users/1')
                 .map(this.extractData)
                 .subscribe(
                     (res: any) => {
                         if (c.value == res.username) {
                             console.log('taken')
                             resolve({'usernameTaken': true})
                         } else {
                             console.log('is not taken')
                             resolve(null)
                         }
                     },
                     err => { console.log(err) }
                 )   
             }
         );

    }

}

I already read some blog posts about this topic, and I also checked two SO questions (1, 2), but I can't get it to work. The service successfully got the server's answer, but when I call it inside the component's validator, the form is going to be invalid every time.

In the examples above, they just call it in the validator section, and I guess the ng2 do the rest of the work in the background, or am I wrong? How is the validator got the promise's value?

5
  • not promises are thrown by the observables, the problem is local. Commented Jan 2, 2017 at 23:41
  • What do you mean? Commented Jan 3, 2017 at 6:31
  • You should consider rephrasing the question to something like: Angular 2.3.1 async custom validator promise doesn't resolve Commented Jan 13, 2017 at 19:34
  • Thanks, I edited! Commented Jan 14, 2017 at 21:03
  • I have spent almost a day for async validations and return status issues, and Voila, your code worked like a charm! Thanks a lot. Commented Aug 29, 2017 at 10:30

1 Answer 1

9

The problem was that I insert the async custom validator into the sync validator section. Which means the 2nd param is for the sync validators, the 3rd one for the async ones.

This works now:

'username': [null,
         [ Validators.required, Validators.minLength(4), Validators.maxLength(12) ],
         [ this.ussr.getUserNameFromServer ]
  ],
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.