在填充组件变量之前调用 Reactive Forms 异步验证器

Reactive Forms async validator is called before component variables are populated

所以我要做的是验证用户名是否已在我的用户编辑表单中被使用。 这是我的表格:

editForm= new FormGroup({
                username: new FormControl('', [Validators.required, Validators.maxLength(60)], this.validateUser.bind(this)),
                fullName: new FormControl('', Validators.maxLength(60)),
                email: new FormControl('', Validators.maxLength(60)),
                phoneNumber: new FormControl('', Validators.maxLength(60)),
            }, { updateOn: "blur"});

在我的验证器中,我在发送验证请求之前检查原始用户名是否已更改,方法是将其与从服务器加载用户信息的变量进行比较:

validateUser(control: FormControl): Observable<ValidationErrors | null> {
    if(control.value != this.originUser.username){
        return this.userService.validateUsername(control.value).pipe(map(res => {
            return res['valid'] ? null : { invalidUsername: true};
        }));
    }
}

如果我尝试将用户名更改为已被其他用户使用但出现错误,一切正常。此外,如果在此之后我将其更改为原始用户名,它也可以正常工作并且不会发送验证请求。

我的 this.originUser 填充在 ngOnInit 中,这是在表单初始化时第一次调用验证器之后发生的,所以我仍然看到发送了带有原始用户名的验证请求,并在以下情况下收到错误消息使用原始用户名加载表单。

ngOnInit() {
            this.userService.getOne(this.id).subscribe(user =>{
                this.editForm.patchValue({
                    username: user.username,
                    fullName: user.fullName,
                    email: user.email,
                    phoneNumber:user.phoneNumber
                });
                this.originUser = user;
            });
        }
    }

打开"Edit user"页面

第一次调用validator时,我无法弄清楚如何不发送验证请求的逻辑

更新: 我想出了如何通过在 ngOnInit 中加载 this.originUser 后添加 this.editForm.get('username').updateValueAndValidity(); 来避免在表单加载时出现错误,但是在加载表单时仍会发送不必要的验证请求。

所以解决方案很简单 将 control.dirty 添加到验证器条件,因此如果用户未更改输入,则永远不会发送请求

validateUsername(control: FormControl): Observable<ValidationErrors | null> {
    if(control.value != this.originUser.username && control.dirty){
        return this.userService.validateUsername(control.value).pipe(map(res => {
            return res['valid'] ? null : { invalidUsername: true};
        }));
    } else return of({});
}