2

Here is the registration form, created with standard angular 2 form builder:

this.form = this.formBuilder.group({
    login : [
        this.formValue.login,
        [
            Validators.required,
            Validators.minLength(loginLength.min),
            Validators.maxLength(loginLength.max),
            regexpValidator(loginPattern),
        ],
        //my custom validator class to check if login already exists
        LoginExistenceValidator,
    ],
    password : [
        this.formValue.password,
        [
            Validators.required,
            Validators.minLength(passwordLength.min),
            Validators.maxLength(passwordLength.max),
        ],
    ],
});

As mentioned here - http://blog.thoughtram.io/angular/2016/03/14/custom-validators-in-angular-2.html#custom-validators-with-dependencies :

It turns out that a validator can also be a class as long as it implements a validate(c: FormControl) method.

Hence it is possible to inject service to acess remote data from validator.

So I created such validator:

import { Injectable, Inject, forwardRef } from '@angular/core';
import { Validator, FormControl }         from '@angular/forms';

import { UsersAdapter } from 'common/adapters/users';

@Injectable()
export class LoginExistenceValidator implements Validator {

    private adapter;

    constructor(@Inject(forwardRef(()=>UsersAdapter)) adapter) {
        debugger
    }

    validate(control: FormControl) {
        console.log("yep i'm called");
        return function(control: FormControl){

            //validation logic

            let validator = new Promise((resolve)=>{
                //mock random success/fail for a while
                setTimeout(()=>{
                    let random = Math.round(Math.random());
                    let value = random ? null : { reserved: true };
                    console.log(resolve);
                    resolve(value);
                },2000);

            });

            return validator;

        }
    }
}

UserAdapter is a wrapper around Angular Http, which retrieves data. Now I'm not using it and every validation call should return random success/fail result.

This code throws such error in browser:

EXCEPTION: Cannot read property 'subscribe' of undefined

Error occured because Angular do not actually calls validate(), and FormControl instance passed to constructor instead of provided UserAdapter service.

When I try to use function instead of class, everything works fine. How can I tell angular to use my validation class properly? Thanks in advance.

1 Answer 1

1

The sentence you quoted was about a validator directive that is applied using a selector on the element.

If you to use it in reactive forms you need to pass a function

The validate() method should return a Promise or Observable not a function that returns an Promise or Observable.

validate(control: FormControl) {
    console.log("yep i'm called");
        return = new Promise((resolve)=>{
            //mock random success/fail for a while
            setTimeout(()=>{
                let random = Math.round(Math.random());
                let value = random ? null : { reserved: true };
                console.log(resolve);
                resolve(value);
            },2000);

        });
    }
}

then use it like

this.form = this.formBuilder.group({
    login : [
        this.formValue.login,
        [
            Validators.required,
            Validators.minLength(loginLength.min),
            Validators.maxLength(loginLength.max),
            regexpValidator(loginPattern),
        ],
        //my custom validator class to check if login already exists
        new LoginExistenceValidator().validate,
    ],
    password : [
        this.formValue.password,
        [
            Validators.required,
            Validators.minLength(passwordLength.min),
            Validators.maxLength(passwordLength.max),
        ],
    ],
});
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. Now it works. I also understand, that in my case Angular do not use dependency injection and it's better to provide validator as a service in constructor.

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.