Angular Custom Async Validation使用Reactive Form和wait in servi



我正试图在Angular中使用AsyncValidation和一个具有async/await的服务方法来测试userName是否存在。我不知道如何在服务(user.service.ts(中转换返回签名

Promise<boolean> 
e.g. 
async isUserNameAvailable(userName: string): Promise<boolean> {
}

Promise<ValidationErrors | null> | Observable<ValidationErrors | null>
e.g.
validate(control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> {
}

在验证器/指令中。

user.service.ts:

async isUserNameAvailable(userName: string): Promise<boolean> {
var query = this.db.collection("users").where("name", "==", userName);
try {
const documentSnapshot = await query.get();
if (documentSnapshot.empty) {
return true;
} else {
return false;
}
} catch (error) {
console.log('Error getting documents', error);
}
}

现有用户名验证器.指令.ts

import { Directive } from '@angular/core';
import { UserService } from './user.service';
import { AbstractControl, ValidationErrors, NG_ASYNC_VALIDATORS, AsyncValidatorFn, AsyncValidator } from '@angular/forms';
import { Observable, timer } from 'rxjs';
import { map, filter, switchMap } from 'rxjs/operators';
export function existingUsernameValidator(userService: UserService): AsyncValidatorFn {
return (control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> => {
let debounceTime = 500; //milliseconds
return Observable.timer(debounceTime).switchMap(()=> { //ERROR BECAUSE OF TIMER
return userService.isUserNameAvailable(control.value).map( //ERROR BECAUSE OF map
users => {
return (users && users.length > 0) ? {"usernameExists": true} : null;
}
);
});
};
} 
@Directive({
selector: '[appExistingUsernameValidator]',
providers: [{provide: NG_ASYNC_VALIDATORS, useExisting: ExistingUsernameValidatorDirective, multi: true}]
})
export class ExistingUsernameValidatorDirective implements AsyncValidator {
constructor(private userService: UserService) {  }
validate(control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> {
return existingUsernameValidator(this.userService)(control);  
}
}

user.component.ts:

name: new FormControl('', {
validators: [Validators.required],
asyncValidators: [existingUsernameValidator(this.userService)]
}),

堆叠闪电战:https://stackblitz.com/edit/angular-ivy-cd866c?file=src%2Fapp%2Fuser.service.ts

有人知道如何使用反应式表单来实现这一点吗?

刚刚纠正了Stacklitz 中的existingUsernameValidator

export function existingUsernameValidator(userService: UserService): AsyncValidatorFn {
return (control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> => {
let debounceTime = 500; //milliseconds
const debounceTimer = timer(debounceTime)
return debounceTimer.pipe(switchMap(()=> {
return userService.isUserNameAvailable(control.value)
.then(result => {
return result ? {"usernameExists": true} : null;
});
}));
};
} 

更新UserService中的isUserNameAvailable

async isUserNameAvailable(userName: string): Promise<boolean> {
const query = this.db.collection("users").where("name", "==", userName);
return query.get()
.then(function(documentSnapshot) {
return (documentSnapshot.empty as boolean) 
})
.catch(function(error) {
console.log("Error getting documents: ", error);
return false;
});
}

试试看,如果一切就绪,请告诉我。还更新了stackblitz

希望它能有所帮助!

编辑:清除后的代码

Vaidator函数

export function existingUsernameValidator(userService: UserService): AsyncValidatorFn {
return (control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> => {
const debounceTime = 500; //milliseconds
return timer(debounceTime).pipe(switchMap(()=> {
return userService.isUserNameAvailable(control.value)
.then(result => result ? {"usernameExists": true} : null);
}));
};
} 

用户服务

async isUserNameAvailable(userName: string): Promise<boolean> {
return this.db.collection("users").where("name", "==", userName).get()
.then(documentSnapshot => documentSnapshot.empty as boolean)
.catch(error => {
console.log("Error getting documents: ", error);
return false;
});
}

existingUsernameValidator更新如下,

import {UserService} from './user.service';
import {AbstractControl, ValidationErrors, NG_ASYNC_VALIDATORS, AsyncValidatorFn, AsyncValidator} from '@angular/forms';
import {from, Observable, timer} from 'rxjs';
import {map, debounceTime} from 'rxjs/operators';
export function existingUsernameValidator(userService: UserService): AsyncValidatorFn {
return (control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> => {
return from(userService.isUserNameAvailable(control.value)).pipe(debounceTime(500),
map(
users => {
return users ? {'usernameExists': true} : null;
}
)
);
};
}

希望这能帮助你

相关内容

  • 没有找到相关文章

最新更新