So, I'm building a food delivery app using flutterflow and firebase as my database. And I stumbled across something a lot of people want to do. Assuming you are familiar with Algolia and to some extent querying and generating children dynamically. Here's a simple method to filter and sort the resulting json to build a listview.
Filtering
Set up an API call with whatever name and add the following:
API url: https://Your_Application_ID.algolia.net/1/indexes/Restaurants/query
Headers- X-Algolia-API-Key: Your_API_Key
X-Algolia-Application-Id: Your_Application_ID
Content-Type: application/json
Body: {
"query": "<query>",
"hitsPerPage": 50,
"aroundLatLng": "<aroundLatLng>",
"aroundRadius": 5000,
"filters": "<filters>",
"attributesToRetrieve": [
"restaurantId",
"name",
"Tags",
"cuisines",
"costfortwo",
"pureveg",
"_geoloc"
]
}
Variables: query, aroundLatLng, filters
And define the json paths using the results from your test api call to use later.
Add the API call to your listview and pass values.
query: *
aroundLatLng: latlang as string not latlang
and filters: we will use a custom function as in the attached image.
I used a dropdown to pass the cuisine and a button to pass the pureVeg values.
Now onto Sorting
We will generate children dynamically from the search results of the API call on the same listview(query with API call and generate children with the results).
We will use a custom function to sort the results. You can find the function in the image too.
The custom function has 3 arguments: searchResultJson(a list of json), order (a string value), jsonPath (a jsonpath string).
You can use whatever method to pass the order and jsonPath but the searchResultJson will be the actual json body from the earlier API call.
The values of order will be either asc or desc(self explanatory I think) and jsonPath value needs to be passed in this format costfortwo.
Hit me up if you need any clarification.
import 'dart:convert';
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart';
import 'package:timeago/timeago.dart' as timeago;
import '/flutter_flow/custom_functions.dart';
import '/flutter_flow/lat_lng.dart';
import '/flutter_flow/place.dart';
import '/flutter_flow/uploaded_file.dart';
import '/backend/backend.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import '/auth/firebase_auth/auth_util.dart';
String? buildAlgoliaFilters(
String? cuisine,
String? pureVeg,
) {
/// MODIFY CODE ONLY BELOW THIS LINE
List<String> filters = [];
if (cuisine != null && cuisine.isNotEmpty) {
filters.add("cuisines:'$cuisine'");
}
if (pureVeg != null && pureVeg.isNotEmpty) {
filters.add("pureveg:'$pureVeg'"); // โ
Now a string: "Yes" or "No"
}
// โ
If filters exist, return them as a combined string
return filters.isNotEmpty ? filters.join(" AND ") : "";
/// MODIFY CODE ONLY ABOVE THIS LINE
}
import 'dart:convert';
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart';
import 'package:timeago/timeago.dart' as timeago;
import '/flutter_flow/custom_functions.dart';
import '/flutter_flow/lat_lng.dart';
import '/flutter_flow/place.dart';
import '/flutter_flow/uploaded_file.dart';
import '/backend/backend.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import '/auth/firebase_auth/auth_util.dart';
List<dynamic>? sortJsonByPath(
List<dynamic>? searchResultJson,
String? order,
String? jsonPath,
) {
/// MODIFY CODE ONLY BELOW THIS LINE
if (searchResultJson == null ||
searchResultJson.isEmpty ||
order == null ||
order.isEmpty ||
jsonPath == null ||
jsonPath.isEmpty) {
return null; // โ
Return null if sorting is not possible
}
// โ
Sort the List
searchResultJson.sort((a, b) {
dynamic valueA = _getValueFromJsonPath(a, jsonPath);
dynamic valueB = _getValueFromJsonPath(b, jsonPath);
// โ
Handle null values (Move them to the end)
if (valueA == null && valueB == null) return 0;
if (valueA == null) return 1;
if (valueB == null) return -1;
// โ
Ensure values are comparable
if (valueA is Comparable && valueB is Comparable) {
return (order.toLowerCase() == 'asc')
? valueA.compareTo(valueB)
: valueB.compareTo(valueA);
}
return 0; // If values are not comparable, keep the order
});
// โ
Extract and return only the sorted list of restaurant IDs
return searchResultJson
.map((item) => item['restaurantId'].toString())
.toList();
}
/// **Helper Function: Extracts Value from Nested JSON**
dynamic _getValueFromJsonPath(dynamic json, String path) {
try {
List<String> keys =
path.split('.'); // โ
Support for nested paths (e.g., "address.city")
dynamic value = json;
for (String key in keys) {
if (value is Map<String, dynamic> && value.containsKey(key)) {
value = value[key];
} else {
return null; // โ
If path is invalid, return null
}
}
return value;
} catch (e) {
return null; // โ
Handle errors gracefully
}
/// MODIFY CODE ONLY ABOVE THIS LINE
}