用户名输入字段的Angular2异步验证器

时间:2016-12-08 13:29:01

标签: angular forms validation asynchronous

我正在尝试验证是否使用了用户名并将结果分配给布尔值:

FileWriter

这将获取一个输入字符串并返回一个布尔值,无论它是否与数据库中的用户匹配。 当使用字符串调用它时,它按预期工作,但我想用字段的输入作为参数调用它,如下所示:

    isUsernameAvailable(control: FormControl) {
   this.authenticationService.isUsernameAvailable(control.value)
       .subscribe(
           result => console.log(result.taken),
           error => console.log(error)
       );
}

我发现当我将它添加到ngOnInit()时,这是有效的:

         this.username = new FormControl(null, 
         Validators.compose([
             Validators.required,
             Validators.minLength(3),
     ]),this.isUsernameAvailable(this.username.value)); // <-- this is wrong obviously

所以我的问题是如何使它成为我的验证器从输入字段中获取输入文本并检查是否采用了用户名。 编辑:当我只使用this.isUsernameAvailable我得到

  

“无法读取属性'authenticationService'未定义”错误

。我也尝试绑定这个:this.isUsernameAvailable.bind(this),但后来我得到了

  

无法读取未定义错误的属性'subscribe'

我还将我的代码更新为我最后的调教。 (控制台日志报告正确的值,但验证程序返回错误)。

1 个答案:

答案 0 :(得分:0)

所以我很清楚我只是不知道自己在做什么,但我却以某种方式让它发挥作用。如果有人遇到同样的问题,我会粘贴我的解决方案。我的最终代码是:

this.username = new FormControl(null, [
            Validators.required,
            Validators.pattern(this.usernamePattern),
            Validators.minLength(3),
            Validators.maxLength(15)
        ], this.validateUsername.bind(this)
    );


  validateUsername(c: FormControl) {
    return this.usernameAvailable(c.value);
}

  private validationTimeout: any;

  usernameAvailable(username: string) {
    clearTimeout(this.validationTimeout);
    return new Promise((resolve) => {
        this.validationTimeout = setTimeout(() => {
            let req = this.authenticationService.isUsernameAvailable(username);
            req.subscribe(result => {
                    if (result.taken) {
                        resolve({taken: true})
                    }
                    else {
                        resolve(null)
                    }
                },
                error => this.logger.error(error.message))
        }, 600);
    });
}

请注意,您无法在异步验证器上直接使用debounceTime,因为它会在每次击键后立即启动,因此您必须以某种方式超时请求。可能有更好的方法,这对我有用。