I've been trying to implement async validation for last few days. But none of the tutorials/solutions are working!
Service code-
getUserIdToCheckDuplicate(userId:any):Observable<any>{
const url = ``; //url goes here
return this.http.get<any>(url);
}
Component code-
ngOnInit(): void {
this.form = this.fb.group({
userId: ['', [Validators.required],[this.validate]]})
}
validate(control: AbstractControl): Observable<ValidationErrors | null> {
console.log(control.value);
return of(control.value)
.pipe(
delay(10),
switchMap((value) =>
this.userService.getUserIdToCheckDuplicate(value).pipe(map(x => {
return x.exists ? { exists: true } : null;
}))
)
);
}
Html code-
<mat-form-field appearance="outline" fxFlex="1 1 calc(25% - 10px)" fxFlex.lt-md="1 1 calc(25% - 10px)"
fxFlex.lt-sm="100%" fxFlex.xs="100%" class="from-color" *ngIf="!data">
<mat-label class="label-padding">User ID</mat-label>
<input class="label-padding" formControlName="userId" matInput placeholder="User ID" required />
<div style="color: red; font-weight: bold;" *ngIf="userId.errors?.exists">Already
Exists !</div>
</mat-form-field>
In the console- console error
In the console, while I write something in the input, with every key storke it prints the value, but after that tells that value is undefined!
What is the reason behind this error? And how can I solve this? It should work properly so that the async validator works fine as well.
Can anyone help me with this please?
CodePudding user response:
I have managed to reproduce the error in the below stackblitz
The problem is that this
in this context does not refer to the class
A simple solution is to simply use arrow function for validate
validate = (control: AbstractControl): Observable<ValidationErrors | null> => {
console.log(control.value);
return of(control.value)
.pipe(
delay(10),
switchMap((value) =>
this.userService.getUserIdToCheckDuplicate(value).pipe(map(x => {
return x.exists ? { exists: true } : null;
}))
)
);
}
See this Here
CodePudding user response:
it's more simple than all this:
validate = (
control: AbstractControl
): Observable<ValidationErrors | null> => {
return this.userService.getUserIdToCheckDuplicate(control.value).pipe(
map(x => {
return x? { exists: true } : null;
})
);
(*)I suppose that your service return null if there're no duplicate
see stackblitz (to check, "fool" is repeat)
If you're using material
<mat-form-field class="name" appearance="outline">
<input matInput placeholder="Name" formControlName="userId">
<mat-error *ngIf="form.get('userId')?.hasError('required')">
Name is required*
</mat-error>
<mat-error *ngIf="form.get('userId')?.hasError('exists')">
Name repeat
</mat-error>
<mat-hint *ngIf="form.get('userId')?.pending">Validating...</mat-hint>
</mat-form-field>
But it's good that check errors 'onblur' (else the error is not showed by defect: in material, if we not use a custom error matcher, the error only is showed if the formControl is touched (edit and blur)
this.form = this.fb.group({
userId: ['', [Validators.required], [this.validate]]
},{updateOn:'blur'});