Reputation: 37
Inside service-
getUserIdToCheckDuplicate(userId:any):Observable<any>{
const url = ``; //url goes here
return this.http.get<any>(url);
}
Inside component-
ngOnInit(): void {
this.form = this.fb.group({
userId: ['', [Validators.required],[this.existingUserIdValidator()]]
}
get userId() {
return this.form.get("userId");
}
existingUserIdValidator(initialID: string = ""): AsyncValidatorFn {
return (
control: AbstractControl
):
| Promise<{ [key: string]: any } | null>
| Observable<{ [key: string]: any } | null> => {
if (control.value === initialID) {
return of(null);
}
else {
return control.valueChanges.pipe(
debounceTime(500),
take(1),
switchMap(_ =>
this.userService
.getUserIdToCheckDuplicate(control.value)
.pipe(
map(user =>
user ? { existingUserId: { value: control.value } } : null
)
)
)
);
}
};
}
Inside html-
<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">
<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.existingUserId">Already Exists !</div>
</mat-form-field>
When I start entering anything the input field, it shows "Cannot read property 'existingUserId' of null".
I've already followed various different ways to perform this async validation. But in my case, those never worked! I don't know where I'm making the mistake! Can anyone help me with this?
Upvotes: 0
Views: 253
Reputation: 4228
The type definition of userId.errors
is ValidationErrors | null
.
So if there is no error, you can't access the existingUserId
property.
You can fix this way : userId.errors?.existingUserId
.
It'll only try to access existingUserId if errors is not null.
About the validator itself, you can't get the validation on the expected value by using valueChanges
.
Here is a solution :
import { timer } from 'rxjs';
existingUserIdValidator(initialID: string = ""): AsyncValidatorFn {
return (
control: AbstractControl
):
| Promise<{ [key: string]: any } | null>
| Observable<{ [key: string]: any } | null> => {
if (control.value === initialID) {
return of(null);
}
else {
return timer(500).pipe(
switchMap(_ =>
this.userService
.getUserIdToCheckDuplicate(control.value)
),
map(user => user ? { existingUserId: { value: control.value } } : null
)
);
}
};
}
Here is a naive sample : https://stackblitz.com/edit/angular-ivy-uv3bv6?file=src%2Fapp%2Fapp.component.html
Upvotes: 1