I’m building a Flutter app with Firestore as the backend database. I have a collection of products, and I’m trying to implement a search functionality that filters products based on a search text and the search is totally generic as it can provide search results regardless of the category of product
class ProductGrid extends StatefulWidget {
final String selectedCategory;
final String searchText;
const ProductGrid(
{Key? key, required this.selectedCategory, required this.searchText})
: super(key: key);
@override
State<ProductGrid> createState() => _ProductGridState();
}
class _ProductGridState extends State<ProductGrid> {
@override
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Expanded(
child: StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection('users')
.doc(FirebaseAuth.instance.currentUser!.uid)
.collection('products')
.where('selectedCategory',
isEqualTo: widget.selectedCategory.isNotEmpty
? widget.selectedCategory
: null)
.where('title', // Filter products by title based on searchText
isGreaterThanOrEqualTo: widget.searchText.toLowerCase(),
isLessThanOrEqualTo: widget.searchText.toLowerCase() + 'z')
.snapshots(),
builder: (context, snapshot) {
print('this: ${widget.searchText}');
print('$snapshot');
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: SpinKitRing(color: primaryBlue, size: 30));
} else if (snapshot.hasData) {
List<Map<String, dynamic>> productsList = snapshot.data!.docs
.map((doc) => doc.data() as Map<String, dynamic>)
.toList();
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 0.88,
mainAxisSpacing: size.height * 0.01,
crossAxisSpacing: size.width * 0.017,
),
itemCount: productsList.length,
itemBuilder: (context, index) {
Map<String, dynamic> productData = productsList[index];
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.white,
),
child: //rest of the code
),
child: //rest of the code
),
);
},
child: Image.asset(
'assets/images/iphoneImage.png',
),
),
),
),
SizedBox(height: size.height * 0.015),
Padding(
padding: const EdgeInsets.only(left: 12),
child: Row(
children: [
Text(
productData['title'],
style: customTextblack,
),
//remaining code fetching titles and products from databse
],
),
),
//remaining code
),
),
),
],
),
),
);
},
);
} else {
return CircularProgressIndicator();
}
},
),
);
}
}
However, when I type a search query in my app, the query doesn’t return any results, even though I have products that match the search text.
I’ve ensured that the search text matches the titles of some products in my database, and the category filtering seems to be working correctly.
Could someone please help me identify why the Firestore query is not returning any results, even though there should be matching products in the database? Any insights or suggestions would be greatly appreciated. Thank you!
My App bar code just incase if you want to have a look into it
class AppSearchBar extends StatelessWidget {
final ValueChanged<String> onChanged;
final String hintText;
const AppSearchBar(
{super.key, required this.hintText, required this.onChanged});
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Container(
height: size.height * 0.06,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Colors.white,
),
child: Center(
child: TextFormField(
onChanged: onChanged,
decoration: InputDecoration(
contentPadding: const EdgeInsets.all(12.0),
prefixIcon: Padding(
padding: const EdgeInsets.all(10.0),
child: SvgPicture.asset(
'assets/images/magnifyingglass.svg',
),
),
iconColor: const Color(0xffC2C2C2),
border: InputBorder.none,
hintText: hintText,
hintStyle: lowOpacityText)),
),
);
}
}
2
Answers
In your firbase quary change like this
This seems wrong:
As far as I know, the correct syntax is:
you’ll also wan to make sure that you have the required index, as what is needed here isn’t auto-created.
Your builder fails to handle errors from the Firestore stream, which is probably why you don’t see any errors. Every builder should start with something like this: