Reputation: 93
I do subscribe to a http request service in my validateUsernameIsUnique
method. I am trying to manipulate the return value of validateUsernameIsUnique()
based on the code inside the subscription. I did read some beginner articles about asynchronous behaviour. Therefore i know the code below is not working because return ret;
is undefined. Unfortunatley i wasn't able to figure out how achieve what i am trying to do.
@Injectable()
export class ValidateService {
constructor(private _authService: AuthService) { }
...
validateUsernameIsUnique = (c: FormControl) => {
let ret;
if (c.value.length >= 3) {
this._authService.uniqueUser({ username: c.value }).subscribe(data => {
if (!data.success) { // Username already exists
ret = { usernameIsTaken: true };
}
else
ret = null;
})
return ret;
}
}
}
The Auth Service i am subscribing to looks like this:
import { Injectable } from '@angular/core';
import { Http, Headers } from '@angular/http';
import 'rxjs/add/operator/map';
@Injectable()
export class AuthService {
authToken: any;
user: any;
constructor(private _http: Http) { }
uniqueUser(user) {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
return this._http.post('http://localhost:3000/users/username', user, { headers: headers })
.map(res => res.json());
}
}
Update1:
Changed code as mentioned in comments to
validateUsernameIsUnique = (c: FormControl) => {
if (c.value.length >= 3) {
return this._authService.uniqueUser({ username: 'zomh' }).map(res =>
{
if (!res.success) { // Username already exists
return { usernameIsTaken: true };
}
else
{
return null;
}
});
}
}
And the Call looks like
ngOnInit() {
this.frmRegisterUser = new FormGroup({
name: new FormControl('',[Validators.required]),
username: new FormControl('',[Validators.required, this._validateService.validateUsernameIsUnique, Validators.minLength(3), this._validateService.validateUsernamePattern]),
email: new FormControl('',[Validators.required, this._validateService.validateEmailPattern]),
password: new FormControl('',[Validators.required, Validators.minLength(6)]),
acceptTerms: new FormControl(false,[Validators.required])
});
Now i am reciving an Object which looks like :
Sorry but i still don't get it where can i find the mapped returning values e.g. { usernameIsTaken: true }
Update2 @pixelbits
It did not work right off the bat: I don't know how to to debug this proper ?, since console.logs won't be printed for async reasons in the inner functions. I tried putting a username 'zomh' which is already in the db (not unique).
uniqueName(): AsyncValidatorFn {
console.log('i am here');
return (control:AbstractControl): Promise<ValidationResult> => {
let q = new Promise<ValidationResult>(
(resolve, reject)=> {
var name = 'zomh';
if (name == '') {
resolve(null);
}
else {
this._authService.uniqueUser({ username: 'zomh' })
.map(t=>t.json())
.subscribe(response=> {
if (response.success === false) {
resolve(response);
}
else
resolve(null);
});
}
});
return q;
}
}
I am getting the "i am here"
in console but thats pretty much it. I get null returned even though it shouldn't with an existing username. I can verifiy the AuthService is working correctly ( tested it with a basic subscribe and username 'zomh').
Upvotes: 1
Views: 3558
Reputation: 52867
It looks you need to implement an asyncronous validator as a factory:
import { AbstractControl, AsyncValidatorFn } from '@angular/forms';
import { Http } from '@angular/http';
import { Injectable, Inject } from '@angular/core';
import 'rxjs/add/operator/map';
interface ValidationResult {
[key:string]:boolean;
}
@Injectable()
export class ValidationService {
constructor(private _authService: AuthService) {
}
validateUsernameIsUnique(): AsyncValidatorFn {
return (control:AbstractControl): Promise<ValidationResult> => {
let q = new Promise<ValidationResult>(
(resolve, reject)=> {
var name = control.value;
if (name == '') {
resolve(null);
}
else {
this._authService.uniqueUser({ username: control.value })
//.map(t=>t.json()) // Auth Service already returning json
.subscribe(response=> {
if (response.success === false)
resolve({ usernameIsTaken: true });
else
resolve(null);
});
}
});
return q;
}
}
}
Make sure you pass the validator as the third parameter (that's where async validators go, the second parameter is for synchronous validators)
this.formGroup = this.fb.group( {
'username': ['hello',, this.validationService.validateUsernameIsUnique()]
});
Upvotes: 1