Please consider the following custom validator function that calls an API on the backend to fetch some data, check them against the current form input and returns an error if the current form input is a duplicate value:
//check to see if the new category name entered is already in the system
categoryNameUnique(c: FormControl) {
let categoryNameAlreadyExists: boolean = false;
//get list of current categories from the server.
return this.inventoryCategoryService.getAll().map(items => {
for (let item of items) {
if (item.Name == c.value) {
categoryNameAlreadyExists = true;
break;
}
}
if (categoryNameAlreadyExists) {
//name is not unique
return { categoryNameUnique: false }
}
//not a duplicate, all good
return null;
});
}
You'll see that this function is returning an observable (as I have to go back to the backend server to fetch some data to do the validation). The validator works like a charm, no issues. However, I don't know how to display an appropriate message to the user when this validator comes back invalid in my corresponding HTML view. If this function was not returning an observable, I'd do something like:
<div *ngIf="form.controls['categoryName'].errors?.categoryNameUnique">
This category name is already taken
</div>
However, since this is an observable that gets returned, the errors Object has properties exposed by the Observable, namely operator
and source
, not the custom object that I'm returning ({categoryNameUnique: false}
).
Any assistance would be appreciated.
Update 1:
Hello all, after trying a few other things, I was able to figure out my own issue.
I was setting up my form validation like so:
constructor(private fb: FormBuilder, private router: Router, private inventoryCategoryService: InventoryCategoryService) {
this.form = fb.group({
'categoryName': [null, Validators.compose([Validators.required, Validators.minLength(3), Validators.maxLength(50), this.categoryNameUnique.bind(this)])]
});
}
The required, minLength and maxLength validators are synchronus but my custom validator categoryNameUnique is async and thus should have been composed separately. I changed the setup to this below and now all is well:
constructor(private fb: FormBuilder, private router: Router, private inventoryCategoryService: InventoryCategoryService) {
this.form = fb.group({
'categoryName': [null, Validators.compose([Validators.required, Validators.minLength(3), Validators.maxLength(50)]),
Validators.composeAsync([this.categoryNameUnique.bind(this)])]
});
}
<div *ngIf="form.controls['categoryName'].errors?.categoryNameUnique">
should work just fine, how does it behave for you? – Max Koretskyioperator
andsource
. If I inspect those two properties, it is not showing me anything related to my categoryNameUnique custom error object that I'm passing back from within the observable. – Tom Vaidyanvalidate
method look? – Max Koretskyi