简体   繁体   English

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

[英]Angular2 async validator for username input field

I'm trying to validate if a username is taken and assign the result to a boolean: 我正在尝试验证是否使用了用户名,并将结果分配给布尔值:

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

This takes an input string and returns a boolean value whether it matches a user in the database or not. 这将使用输入字符串,并返回一个布尔值,无论它是否与数据库中的用户匹配。 It works as expected when called with a string, but I want to call it with the field's input as parameter like this: 使用字符串调用时,它可以按预期工作,但是我想使用字段输入作为参数来调用它,如下所示:

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

I found out that this works when I add it to ngOnInit() : 我发现将其添加到ngOnInit()时可以使用:

     this.username.valueChanges.debounceTime(400).subscribe(value => {return this.isUsernameAvailable(value) });

So my question is how to make it so my validator takes the input text from the input field and checks if the username is taken. 所以我的问题是如何做到这一点,以便我的验证器从输入字段中获取输入文本,并检查是否使用了用户名。 EDIT: When I use only this.isUsernameAvailable I get 编辑:当我只使用this.isUsernameAvailable我得到

"Cannot read property 'authenticationService' of undefined" error “无法读取未定义的属性'authenticationService'”错误

. I also tried to bind this: this.isUsernameAvailable.bind(this), but then I get 我也尝试将其绑定:this.isUsernameAvailable.bind(this),但随后我得到了

Cannot read property 'subscribe' of undefined error 无法读取未定义错误的属性“订阅”

I also updated my code to what I last tempered with. 我也将代码更新为上次修改的代码。 (the console log reports the correct value, but the validator returns errors). (控制台日志报告正确的值,但验证器返回错误)。

So apparantely I just don't know what I'm doing, but I got it working somehow. 因此,显然我只是不知道自己在做什么,但是我以某种方式使它工作了。 I'm pasting my solution if someone ever is stuck on the same problem. 如果有人遇到相同的问题,我将粘贴我的解决方案。 My final code is: 我的最终代码是:

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

Keep in mind that you can't use debounceTime directly on the async validator, as it will always initiate immediately after each keystroke, so you have to timeout your request somehow. 请记住,您不能直接在异步验证器上使用debounceTime,因为它总是在每次击键后立即启动,因此您必须以某种方式使请求超时。 There's probably a better way to do it, this is what worked for me. 可能有更好的方法,这对我有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM