Angular 2异步表单验证器

时间:2016-10-20 08:32:56

标签: angular rxjs angular2-forms angularfire2

实际上我遇到了这个问题。

我已经创建了一个自定义异步验证程序来检查是否使用了用户名。这是我绑定它的地方:

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

这是我的验证员:

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$;
};

所以这个验证器有效。如果使用用户名,则记录“Username taken”,否则记录“Username available”。

我的问题:返回语句不起作用。当我订阅表单的状态时,它仍然是“待定”而不是“有效”或“无效”。 Angular2认为验证仍在运行。

有没有人知道如何根据observables创建有效的return或resolve语句?

也许我自己订阅并使用resolve()函数执行某些操作。但我所有的尝试都没有奏效。

提前致谢!!!

2 个答案:

答案 0 :(得分:3)

您可以尝试.first()以确保在第一个事件发生后关闭可观察信息:

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

不确定这是否是实际问题。

答案 1 :(得分:0)

我有类似的问题。就我而言,我有类别列表,我想检查类别名称是否唯一。这是我的验证器:

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;
      });
  }
}

正如您所看到的,您可以在数据库上进行搜索(性能更高),然后使用一次返回Promise。