Skip to main content
RapidDev - Software Development Agency
flutterflow-tutorials

How to Build an E-Commerce Product Filter in FlutterFlow

Build an advanced product filtering system with multi-select category ChoiceChips, a price range RangeSlider Custom Widget, a minimum rating Slider, a sort DropDown, and an in-stock toggle Switch. All filter selections are stored in a Page State Map called activeFilters. On apply, a Firestore query is composed with chained where clauses matching the selected filters and sort order. A filter count Badge on the filter icon shows how many filters are active, and a Reset button clears everything back to defaults.

What you'll learn

  • How to build a multi-faceted filter panel with ChoiceChips, Sliders, and Switches
  • How to compose dynamic Firestore queries from multiple filter criteria
  • How to display active filter count and implement a Reset button
  • How to handle Firestore composite index requirements for compound queries
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Advanced8 min read30-40 minFlutterFlow Free+March 2026RapidDev Engineering Team
TL;DR

Build an advanced product filtering system with multi-select category ChoiceChips, a price range RangeSlider Custom Widget, a minimum rating Slider, a sort DropDown, and an in-stock toggle Switch. All filter selections are stored in a Page State Map called activeFilters. On apply, a Firestore query is composed with chained where clauses matching the selected filters and sort order. A filter count Badge on the filter icon shows how many filters are active, and a Reset button clears everything back to defaults.

Building an Advanced Product Filter in FlutterFlow

This tutorial focuses specifically on the product filtering UI and query logic for an e-commerce app. While a full store includes cart, checkout, and payment, the filter system is often the most complex UI component. You will build a Bottom Sheet filter panel with category selection, price range, rating threshold, sort order, and stock availability. The challenge is composing Firestore queries that combine multiple where clauses while respecting composite index requirements. This pattern applies to any catalog: products, listings, events, or job posts.

Prerequisites

  • A FlutterFlow project with Firestore configured
  • A products collection with category, price, rating, and inStock fields
  • Basic understanding of Backend Queries and Page State in FlutterFlow
  • At least 15-20 sample products with varied field values for testing

Step-by-step guide

1

Set up the products collection and sample data

Create a products collection with fields: name (String), price (double), category (String: Electronics, Clothing, Home, Sports, Books), rating (double, 1.0 to 5.0), reviewCount (int), inStock (bool), imageUrl (String), description (String), createdAt (Timestamp). Add 15-20 products spanning all categories with varied prices (5 to 500), ratings (1.0 to 5.0), and a mix of in-stock and out-of-stock items. This variety is essential for testing filter combinations.

Expected result: Firestore has a products collection with diverse sample data for all filter scenarios.

2

Build the product grid with a filter icon and active filter badge

Create a ProductsPage. Add Page State: activeFilters (JSON/Map, default empty), selectedCategories (String List, default empty), minPrice (double, default 0), maxPrice (double, default 1000), minRating (double, default 0), sortBy (String, default 'newest'), inStockOnly (bool, default false). Display products in a GridView with responsive crossAxisCount (2 on mobile, 3 on tablet). At the top, add a Row with a search TextField and a Stack containing a filter IconButton with a Badge overlay showing the count of active filters. Tapping the filter icon opens the filter Bottom Sheet.

Expected result: A product grid displays with a filter icon that shows how many filters are currently active.

3

Create the filter Bottom Sheet with all filter controls

Create a Bottom Sheet with sections: Categories as multi-select ChoiceChips (Electronics, Clothing, Home, Sports, Books, with All as default). Price Range as a Custom Widget RangeSlider with min 0 and max 1000, displaying the selected range values. Minimum Rating as a Slider from 0 to 5 with 0.5 step increments, showing star icons. Sort By as a DropDown with options: Newest, Price Low to High, Price High to Low, Most Popular, Highest Rated. In Stock Only as a Switch toggle. At the bottom, add a Row with a Reset button (clears all filters to defaults) and an Apply button (saves to Page State and closes the sheet).

price_range_slider.dart
1// Custom Widget: PriceRangeSlider (Dart)
2import 'package:flutter/material.dart';
3
4class PriceRangeSlider extends StatefulWidget {
5 final double min;
6 final double max;
7 final double initialStart;
8 final double initialEnd;
9 final Function(double, double) onChanged;
10
11 const PriceRangeSlider({
12 required this.min,
13 required this.max,
14 required this.initialStart,
15 required this.initialEnd,
16 required this.onChanged,
17 });
18
19 @override
20 State<PriceRangeSlider> createState() => _PriceRangeSliderState();
21}
22
23class _PriceRangeSliderState extends State<PriceRangeSlider> {
24 late RangeValues _values;
25
26 @override
27 void initState() {
28 super.initState();
29 _values = RangeValues(widget.initialStart, widget.initialEnd);
30 }
31
32 @override
33 Widget build(BuildContext context) {
34 return Column(children: [
35 RangeSlider(
36 values: _values,
37 min: widget.min,
38 max: widget.max,
39 divisions: 100,
40 labels: RangeLabels(
41 '\$${_values.start.round()}',
42 '\$${_values.end.round()}',
43 ),
44 onChanged: (v) {
45 setState(() => _values = v);
46 widget.onChanged(v.start, v.end);
47 },
48 ),
49 Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
50 Text('\$${_values.start.round()}'),
51 Text('\$${_values.end.round()}'),
52 ]),
53 ]);
54 }
55}

Expected result: A Bottom Sheet displays all filter controls: categories, price range, rating, sort, and stock toggle.

4

Compose the Firestore query from active filters

On Apply tap in the filter Bottom Sheet, build the Backend Query dynamically. Start with the products collection. If selectedCategories is not empty and does not include All, add a where clause: category IN selectedCategories (Firestore whereIn, max 10 values). Add where price >= minPrice AND price <= maxPrice. Add where rating >= minRating. If inStockOnly is true, add where inStock == true. Apply orderBy based on sortBy: newest orders by createdAt descending, price options order by price ascending or descending, popular orders by reviewCount descending, highest rated orders by rating descending. Update the product GridView with the filtered query results.

Expected result: The product grid updates to show only products matching all selected filter criteria.

5

Add filter count badge and reset functionality

Calculate the active filter count: increment by 1 for each non-default filter (categories selected, price range changed from 0-1000, rating above 0, sort changed from newest, inStockOnly enabled). Display this count in a Badge widget overlaid on the filter IconButton, using Conditional Visibility to hide the badge when count is 0. The Reset button in the Bottom Sheet sets all Page State filter values to their defaults, recalculates the count to 0, and re-runs the default query. Also add a chip row below the filter icon showing active filters as removable Chips that the user can tap to remove individually.

Expected result: The filter badge shows the active count, and users can reset all filters or remove individual ones.

Complete working example

FlutterFlow Product Filter Setup
1FIRESTORE DATA MODEL:
2 products/{productId}
3 name: String
4 price: double
5 category: String (Electronics / Clothing / Home / Sports / Books)
6 rating: double (1.0 - 5.0)
7 reviewCount: int
8 inStock: bool
9 imageUrl: String
10 description: String
11 createdAt: Timestamp
12
13PAGE: ProductsPage
14 PAGE STATE:
15 selectedCategories: List<String> = []
16 minPrice: double = 0
17 maxPrice: double = 1000
18 minRating: double = 0
19 sortBy: String = 'newest'
20 inStockOnly: bool = false
21 activeFilterCount: int = 0
22
23 WIDGET TREE:
24 Column
25 Row
26 TextField (search)
27 Stack
28 IconButton (filter icon open BottomSheet)
29 Badge (activeFilterCount, hidden if 0)
30 Wrap (active filter Chips, removable)
31 GridView (crossAxisCount: 2)
32 ProductCard
33 Image (imageUrl)
34 Text (name)
35 Text (price formatted)
36 Row (rating stars + reviewCount)
37
38BOTTOM SHEET: FilterPanel
39 SingleChildScrollView
40 Column
41 Text ("Categories")
42 ChoiceChips (multi-select: All / Electronics / Clothing / ...)
43 Text ("Price Range")
44 Custom Widget (PriceRangeSlider: min 0, max 1000)
45 Text ("Minimum Rating")
46 Slider (0 to 5, step 0.5, with star label)
47 Text ("Sort By")
48 DropDown (Newest / Price Low-High / Price High-Low / Popular / Top Rated)
49 Row
50 Text ("In Stock Only")
51 Switch (inStockOnly)
52 Row
53 Button ("Reset" clear all to defaults)
54 Button ("Apply" compose query + close sheet)
55
56QUERY COMPOSITION (on Apply):
57 query = products collection
58 if categories != empty && !includes('All'):
59 query = query.where('category', whereIn: selectedCategories)
60 query = query.where('price', >=, minPrice)
61 query = query.where('price', <=, maxPrice)
62 query = query.where('rating', >=, minRating)
63 if inStockOnly:
64 query = query.where('inStock', ==, true)
65 switch (sortBy):
66 'newest' orderBy('createdAt', desc)
67 'priceLow' orderBy('price', asc)
68 'priceHigh' orderBy('price', desc)
69 'popular' orderBy('reviewCount', desc)
70 'topRated' orderBy('rating', desc)
71
72COMPOSITE INDEXES REQUIRED:
73 category + price + createdAt
74 category + rating + price
75 inStock + price + createdAt
76 (create in Firebase Console for each common combination)

Common mistakes when building an E-Commerce Product Filter in FlutterFlow

Why it's a problem: Chaining too many Firestore where clauses without composite indexes

How to avoid: Pre-create composite indexes in Firebase Console for your most common filter combinations. Check the Firestore error logs for the exact index creation URL when a new combination is needed.

Why it's a problem: Using whereIn with more than 10 category values

How to avoid: Limit category ChoiceChips to 10 or fewer options. For more categories, use a hierarchical approach with parent categories containing subcategories.

Why it's a problem: Applying filters on the client instead of in the Firestore query

How to avoid: Always push filter logic into the Firestore query with where clauses. Only filter client-side for criteria that Firestore cannot express in a single query.

Best practices

  • Pre-create Firestore composite indexes for common filter and sort combinations
  • Use Page State to track all filter values so they persist while browsing
  • Show an active filter count badge so users know filters are applied
  • Provide a Reset button to clear all filters in one tap
  • Display active filters as removable Chips below the search bar for quick access
  • Limit whereIn arrays to 10 values maximum per Firestore constraints
  • Test filter combinations with varied sample data to catch empty-result edge cases
  • Default to showing in-stock items first for better user experience

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I want to build an advanced product filter system in FlutterFlow with multi-select category ChoiceChips, a price range RangeSlider Custom Widget, a minimum rating Slider, a sort DropDown, and an in-stock toggle. Filters compose a Firestore query with chained where clauses. Give me the data model, Bottom Sheet widget tree, query composition logic, and required composite indexes.

FlutterFlow Prompt

Create a product grid page with a filter icon in the top right. Add a bottom sheet with category chips, a price range slider, a star rating slider, a sort dropdown, an in-stock toggle switch, and Reset and Apply buttons at the bottom.

Frequently asked questions

How do I handle Firestore composite index errors?

When a query fails due to a missing composite index, Firestore logs the exact index creation URL in the console. Click that link to auto-create the index. Pre-create indexes for your most common filter and sort combinations.

Can I add a text search filter alongside the other filters?

Firestore does not support full-text search natively. For basic prefix matching, use where name >= searchTerm and name <= searchTerm + unicode high character. For full search, integrate Algolia or Typesense via a Cloud Function.

How do I persist filter selections when navigating away and back?

Store filter values in App State (persisted) instead of Page State. When the user returns to the products page, read from App State to restore their previous filters.

What if I have more than 10 categories?

Firestore whereIn supports a maximum of 10 values. Group categories into parent categories with subcategories, or run multiple queries for batches of 10 categories and merge the results.

How do I show a no results message when filters are too restrictive?

Check the length of the query results. If zero, display a Column with an illustration and text suggesting the user broaden their filters or tap Reset to clear all criteria.

Can RapidDev help build a complete e-commerce filtering system?

Yes. RapidDev can build sophisticated product catalogs with faceted search, full-text search integration, personalized recommendations, and analytics on filter usage patterns.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.