3

I am trying to create a async custom validator to check if a username already exist in a signup form. I have created a service class which calls the Web API (as below) to check the unique user name.

I also created a async custom validator which suppose to call the service and perform the validation. However I am stuck trying to understand how to inject the service into the validator. The service also get injected with Http.

Anyone has any idea how this validation can be done properly?

-Alan-

Custom Validator

export class UserNameValidators {
    static shouldBeUnique(control: FormControl) {
           ....
           //Need to call the Signup service here
        }
    }

Service

@Injectable()
export class SignUpService
{
        constructor(private http: Http) {

          }
shouldBeUnique(username: string): Observable<boolean> {
        let headers = new Headers();
        headers.append('Content-Type', 'application/x-www-form-urlencoded');
        let options = new RequestOptions({ headers: headers });

               return this.http.post('localhost/authentication/api/accounts/user/' + username, '', options)
            .map((response: Response) => {
                let result = response.toString();
                if (result === 'true')
                    return true

                return false;
            })
            .catch((error: any) => {
                if (error.status === 400) {
                    var cleandata = error._body
                        .replace(/\\n/g, "\\n")
                        .replace(/\\'/g, "\\'")
                        .replace(/\\"/g, '\\"')
                        .replace(/\\&/g, "\\&")
                        .replace(/\\r/g, "\\r")
                        .replace(/\\t/g, "\\t")
                        .replace(/\\b/g, "\\b")
                        .replace(/\\f/g, "\\f");

                    cleandata = cleandata.replace(/[\u0000-\u001F]+/g, "");

                    return Observable.throw(new Error("Unknown Error"));
                }

            });
    }
}

Update

App.Module

@NgModule({
    imports     : [BrowserModule, HomeModule, SignupModule,signupRouting, routing],
    declarations: [AppComponent],
    providers   : [AuthService, AuthGuard, SignupService],
    bootstrap   : [AppComponent]
})

Custom Validator

export class UserNameValidators {

    constructor(private service: SignupService) { }

    shouldBeUnique(control: FormControl) {
        return new Promise((resolve, reject) => {

            this.service.shouldBeUnique(control.value).subscribe(
                data => {
                    if (data.length == 0 || data.length == 1) {
                        resolve(null);
                    } else {
                        resolve({ shouldBeUnique: true });
                    }
                },
                err => {
                    resolve({ shouldBeUnique: true });
                }
            )
        });

    }
}

Signup.component

export class SignupComponent implements OnInit {
    form: FormGroup;
    signedUp: boolean = false;
    error = '';

    constructor(private fb: FormBuilder, private router: Router, private signupService: SignupService) { }

    ngOnInit() {
        this.form = this.fb.group({
            firstname: ['', Validators.required],
            lastname: ['', Validators.required],
            username: ['', Validators.compose([Validators.required, UserNameValidators.notValidEmail]), new UserNameValidators(this.signupService).shouldBeUnique],

            password: ['', Validators.compose([Validators.required, UserNameValidators.cannotContainSpace])],
            confirmpassword: ['', Validators.compose([Validators.required, UserNameValidators.cannotContainSpace])]
        }, { validator: this.matchingPasswords('password', 'confirmpassword') });
    }
}

1 Answer 1

2

However I am stuck trying to understand how to inject the service into the validator

I assume that is your question:

You need to register your service as a provider in your app.module:

@NgModule({ 
    // imports, etc
    providers: [
    appRoutingProviders,
    SignUpService]})

Decorate your service with @Injectable():

@Injectable()
export class SignUpService {
// your service...

Add a constructor to your validator that takes SignUpService:

constructor(private signUpService: SignUpService)
{

}
Sign up to request clarification or add additional context in comments.

1 Comment

changed based on your answer (the question is edited) , however, it looks like the service is not properly injected. It complaint "EXCEPTION: Cannot read property 'service' of undefined"

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.