Search code examples
angularangular-reactive-formsangular-validation

Reactive Forms async validator is called before component variables are populated


So what I'm trying to do is validate if username is already taken or not in my user edit form. Here is my form:

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

In my validator I check if original username is changed before sending validation request by comparing it to variable which has user info loaded from server:

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

Everything works fine if I try to change username to already taken by another user and I get an error. Also if after this I change it to original username it also works fine and validation request is not sent.

My this.originUser is populated in ngOnInit and this happens after validator is called for the first time on form initialization so I still see a validation request with original username is sent and get an error when form loads with original username.

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

I cant figure out the logic how not to send validation request when validator is called for the first time when I open "Edit user" page

UPD: I figured out how not to get error on form load by adding this.editForm.get('username').updateValueAndValidity(); after i load this.originUser in ngOnInit but unnecessary validation request is still sent when form loads.


Solution

  • So the solution was quite simple Added control.dirty to validator condition so request is never sent if user didnt change the input

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