I am trying to make a dynamic search form on a website with Angular 8, where the user can use different dropdown menus to choose what to search for in Firestore. Depending on the different choices, I have a function that makes a string that has the same form as the query should, although it's a string. But I can't figure out how to then use it together with valueChanges()
like I want to, as it's still a string. It this possible?
I guess this isn't a very elegant (if at all possible) way to do this dynamic querying, but if it's possible I think it would save me valuable time at the moment. (I have also seen how to make filters with BehaviourSubjects and switchMap
, so I guess that is another (better?) way if this doesn't work.)
async getRealTimeData(value) {
this.query = await this.makeQuery(value);
this.data = this.query.valueChanges();
}
async makeQuery(value) {
var collection: string;
switch (value.collection) {
case 'X':
collection = 'X';
this.queryString = ".where('datetime', '>=', '2020-01-15T09:51:00.000Z')";
break;
case 'Y':
collection = 'Y';
this.queryString = ".orderBy('ID', 'asc')";
break;
}
// If Z chosen, add to search string
if (value.Z) {
this.queryString = this.queryString.concat(".where('Z', '==', value.Z)");
}
// If not viewAllUser, add list of permitted
else if (this.authService.viewAllUser == false) {
this.queryString = this.queryString.concat(".where('ID', 'in', this.permitted");
}
this.queryString = this.queryString.concat(".orderBy('datetime', 'desc')");
// If realtime, add limit to search string
// (If download: no limit)
if (this.searchType == "realtime") {
this.queryString = this.queryString.concat('.limit(100)');
}
this.query = this.query.concat(this.queryString).concat(')');
console.log('Query: ',this.query);
return this.query;
}
You'll want to stop using strings for defining the query. To turn a string into executable code, you'd have to eval()
is, which is not a secure operation in many environments. But it's also not needed, as you can instead use a similar pattern to build the query up too.
async makeQuery(value) {
switch (value.collection) {
case 'X':
this.query = this.query.where('datetime', '>=', '2020-01-15T09:51:00.000Z');
break;
case 'Y':
this.query = this.query.orderBy('ID', 'asc');
break;
}
// If Z chosen, add to query
if (value.Z) {
this.query = this.query.where('Z', '==', value.Z);
}
// If not viewAllUser, add list of permitted
else if (this.authService.viewAllUser == false) {
this.query = this.query.where('ID', 'in', this.permitted);
}
this.query = this.query.orderBy('datetime', 'desc');
// If realtime, add limit to search string
// (If download: no limit)
if (this.searchType == "realtime") {
this.query = this.query.limit(100);
}
return this.query;
}
You'll see that the code is very similar to yours still, but now builds the actual query, instead of concatenating strings.