1

Actually I stuck in this problem.

I've created a custom async validator to check if a username ist taken or not. This is where I bind it:

 'name': ['',[Validators.required, Validators.minLength(4), Validators.minLength(4)], this.asyncName.bind(this)],

And this is my Validator:

asyncName(control: FormControl) {
    this.names$ = this.af.database.list('/usernames')
     .map (name => {
            name.filter(name => {
                if (name.name.toLowerCase() === control.value.toLowerCase()) {
                     console.log("Username taken");  
                     return {
                        valid: false
                    }; 
                } else {
                    console.log("Username available");
                    return {
                        valid: true
                    };
                }
            })
        });             

    return this.names$;
};

So this validator works. If the user name is taken it logs "Username taken" else "Username available".

My Problem: The return statement is not working. When I subscribe to the state of the form it would be still "Pending" and not "Valid" or "Invalid". Angular2 thinks the Validation is still running.

Does anyone know how to create valid return or resolve statement based on observables?

Maybe to subscribe by my self and do something with the resolve() function. But all my attempts were not working.

Thanks in advance!!!

2 Answers 2

3

You can try .first() to ensure the observable closes after the first event:

asyncName(control: FormControl) {
    this.names$ = this.af.database.list('/usernames').first()
    .map(...

Not sure if this is the actual problem.

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

Comments

0

I had similar problem. In my case, I had categories list and I wanted to check if a category name is unique or not. This is my validator:

export class CategoryFormComponent {
  constructor(
    private firebase: AngularFireDatabase
  ) {}
  
   categoryExists(control: AbstractControl) {
    return  this.firebase.database
        .ref(`categories/${this.uid}`) // user's uid
        .orderByChild('name')
        .equalTo(control.value)
        .once('value')
        .then((snapshot) => {
          return snapshot.val() ? { categoryExists: true } : null;
      });
  }
}

As you can see you can make search on database (more performant) and then use once which returns Promise.

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.