I am using the angular forms validation to attempt to check if a given value is already in use in a set of data.
The app I am building is an online auction platform so I have a structure where 'Items' belong to 'Auctions' and each item within a given auction should have a unique "Lot Number." It is also important that the user be able to assign the lot number manually, rather than it being an auto-assigned index.
When a seller is inputing information about a a new Item I want to perform a check on my database (Firebase) to determine in a given lot number has already been used in the given auction. I am trying to perform this check as an asynchronous angular form validator.
The code I have is this:
Note: this.data
is the name of a service where I keep functions which hit the database. They return observables.
uniqueLotNumberValidator(control: FormControl){
return this.data.getItemsByAuction_snapshot(this.auctionId).map((itemsSnapList) => {
let itemObservableArray = [];
itemsSnapList.forEach((snap) => {
itemObservableArray.push(this.data.getItemLotNumberById(snap.key));
})
forkJoin(itemObservableArray).subscribe(lotNumbers => {
let i = lotNumbers.length;
while (i--) {
if (lotNumbers[i] == control.value) {
console.log('already in use');
return { dubNumber: true };
}
}
console.log('lot number is unique');
return null;
});
});
}
To walk through what I am trying to do:
First, data.getItemsByAuction_snapshot
returns an observable which provides a list of item keys that belong to the auction.
Then I populate an array with an observable (that returns the lot number) for each of the keys so that I can do a forkJoin and get an array back of each lot number in use in the auction.
With the result of that forkjoin I now have an array of all of the lot numbers in use and I loop through them to compare each to the value of the user input.
If the user's provided value matches one of the values already in use I want the validator to fail. If however it is unique the validator should read as valid.
This is not behaving as I would hope. I suspect my error lies in my not fully grasping observables. Any help understanding the error here would be appreciated.
The solution I found was to return a new promise and place my code inside it:
uniqueLotNumberValidator(control: FormControl){
return new Promise((resolve, reject) => {
this.data.getItemsByAuction_snapshot(this.auctionId).subscribe((itemsSnapList) => {
let itemObservableArray = [];
itemsSnapList.forEach((snap) => {
itemObservableArray.push(this.data.getItemLotNumberById(snap.key));
});
forkJoin(itemObservableArray).subscribe(lotNumbers => {
let i = lotNumbers.length;
while (i--) {
if (lotNumbers[i] == control.value) {
resolve({ dubNumber: true });
}
}
resolve(null);
});
});
});
}
It works as expected.