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

How to Implement Dynamic Sorting and Filtering in a FlutterFlow E-Commerce App

Build a sort-plus-filter state machine for a FlutterFlow e-commerce app. Page State tracks the active sort field, sort direction, and applied filters. A Backend Query composes the Firestore query dynamically based on these states, handling Firestore's composite index requirements. When Firestore cannot combine an inequality filter with a different orderBy field, a Custom Function fetches a broader result set and sorts client-side as a fallback.

What you'll learn

  • How to build a sort and filter state machine using Page State variables
  • How to compose Firestore queries dynamically with sort and filter combinations
  • How to handle Firestore composite index limitations with client-side fallbacks
  • How to display active filters as removable chips with sort direction indicators
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Advanced8 min read25-30 minFlutterFlow Free+March 2026RapidDev Engineering Team
TL;DR

Build a sort-plus-filter state machine for a FlutterFlow e-commerce app. Page State tracks the active sort field, sort direction, and applied filters. A Backend Query composes the Firestore query dynamically based on these states, handling Firestore's composite index requirements. When Firestore cannot combine an inequality filter with a different orderBy field, a Custom Function fetches a broader result set and sorts client-side as a fallback.

Building Dynamic Sort and Filter for E-Commerce in FlutterFlow

E-commerce apps need both sorting (by price, rating, date) and filtering (by category, price range, availability). The challenge is that Firestore has strict rules about combining inequality filters with orderBy on different fields. This tutorial builds a state machine that composes queries when possible and falls back to client-side sorting when Firestore limitations prevent server-side execution.

Prerequisites

  • A FlutterFlow project with Firestore configured
  • A products collection with fields: name, price, rating, category, createdAt, inStock
  • Understanding of Firestore query limitations and composite indexes
  • Familiarity with Page State and Custom Functions in FlutterFlow

Step-by-step guide

1

Set up Page State variables for sort and filter tracking

Create the following Page State variables on your product listing page: sortField (String, default 'createdAt'), sortDirection (String, default 'desc'), filterCategory (String, default empty for no filter), filterMinPrice (double, default 0), filterMaxPrice (double, default 99999), filterInStock (Boolean, default false). These variables form the state machine that drives the query composition. Every sort or filter UI change updates one of these variables, which triggers a query refresh.

Expected result: Page State contains all sort and filter parameters ready to drive dynamic Firestore queries.

2

Build the sort selector with direction toggle

Add a Row at the top of the product listing page. Include a DropDown with sort options: Newest (createdAt desc), Price Low to High (price asc), Price High to Low (price desc), Highest Rated (rating desc), Most Popular (viewCount desc). When a sort option is selected, update both sortField and sortDirection in Page State. Add an IconButton next to the DropDown showing an up or down arrow based on sortDirection. Tapping it toggles between asc and desc and updates the Page State.

Expected result: Users select a sort criterion from the dropdown and toggle ascending or descending order with the arrow button.

3

Build the filter panel with category, price range, and stock toggle

Add a filter section using ChoiceChips for category selection (All, Electronics, Clothing, Home, Sports). When a chip is selected, update filterCategory. Add a RangeSlider for price range that updates filterMinPrice and filterMaxPrice. Add a Switch labeled In Stock Only that updates filterInStock. Display the active filters below the controls as colored removable chips: each chip shows the filter value with an X button that resets that specific filter to its default value.

Expected result: Users apply category, price range, and stock filters with visual feedback showing active filter chips.

4

Compose the Firestore query dynamically from Page State

Create a Backend Query on the products collection. Build the query based on Page State: if filterCategory is not empty, add whereEqualTo on category. If filterInStock is true, add whereEqualTo inStock == true. For price range, add where price >= filterMinPrice and price <= filterMaxPrice. Add orderBy using sortField and sortDirection. Important: when using a price range filter (inequality on price), Firestore requires the first orderBy to be on the price field. If the user wants to sort by rating while filtering by price, the query will fail without a composite index or a workaround.

Expected result: The product grid updates dynamically as users change sort and filter settings via Firestore query recomposition.

5

Handle Firestore limitations with client-side sort fallback

Firestore requires the first orderBy field to match the inequality filter field. When a user filters by price range but sorts by rating, this conflicts. Detect this case: if sortField is not 'price' AND price range filter is active, fetch products with the price filter and orderBy price, then apply a Custom Function that re-sorts the results by the desired sortField client-side. The Custom Function accepts the product list and sortField and sortDirection, then returns the re-sorted list. Display the Custom Function output instead of the raw query results.

sort_products.dart
1// Custom Function: sortProducts
2List<dynamic> sortProducts(
3 List<dynamic> products,
4 String sortField,
5 String sortDirection,
6) {
7 final sorted = List<dynamic>.from(products);
8 sorted.sort((a, b) {
9 final aVal = a[sortField] ?? 0;
10 final bVal = b[sortField] ?? 0;
11 if (aVal is num && bVal is num) {
12 return sortDirection == 'asc'
13 ? aVal.compareTo(bVal)
14 : bVal.compareTo(aVal);
15 }
16 return 0;
17 });
18 return sorted;
19}

Expected result: All sort and filter combinations work, with Firestore handling what it can and client-side sorting covering the rest.

6

Display results count and add a clear all filters button

Below the filter chips, show a Text displaying the results count: '{n} products found'. Add a Clear All button that resets all Page State filter variables to their defaults and sortField to 'createdAt' desc. This refreshes the query to show all products in default order. Also add empty state handling: when the query returns zero results, show a Container with an illustration and text 'No products match your filters. Try adjusting your criteria.' with a Clear Filters button.

Expected result: Users see how many products match their criteria and can clear all filters with one tap.

Complete working example

FlutterFlow Sort and Filter Setup
1FIRESTORE DATA MODEL:
2 products/{productId}
3 name: String
4 price: double
5 rating: double (0-5)
6 category: String
7 createdAt: Timestamp
8 inStock: Boolean
9 viewCount: int
10 imageUrl: String
11
12 COMPOSITE INDEXES (create in Firebase Console):
13 products: category ASC, price ASC
14 products: category ASC, rating DESC
15 products: category ASC, createdAt DESC
16 products: inStock ASC, price ASC
17
18PAGE STATE:
19 sortField: String = 'createdAt'
20 sortDirection: String = 'desc'
21 filterCategory: String = '' (empty = all)
22 filterMinPrice: double = 0
23 filterMaxPrice: double = 99999
24 filterInStock: Boolean = false
25
26QUERY COMPOSITION LOGIC:
27 1. Start with products collection reference
28 2. If filterCategory != '' .where('category', isEqualTo: filterCategory)
29 3. If filterInStock == true .where('inStock', isEqualTo: true)
30 4. If filterMinPrice > 0 OR filterMaxPrice < 99999
31 .where('price', isGreaterThanOrEqualTo: filterMinPrice)
32 .where('price', isLessThanOrEqualTo: filterMaxPrice)
33 MUST orderBy 'price' first (Firestore rule)
34 If sortField != 'price' fetch with price order, then sort client-side
35 5. Else .orderBy(sortField, descending: sortDirection == 'desc')
36
37WIDGET TREE:
38 Column
39 Row (Sort controls)
40 DropDown (sort options: Newest, Price , Price , Rating, Popular)
41 IconButton (asc/desc toggle arrow)
42 SizedBox (8)
43 Row (Filter controls)
44 ChoiceChips (category: All, Electronics, Clothing, Home, Sports)
45 RangeSlider (price range)
46 Switch (In Stock Only)
47 Row (Active filters)
48 Wrap (filter chips with X remove)
49 Spacer
50 Text ('{n} products')
51 TextButton 'Clear All'
52 SizedBox (16)
53 GridView (2 columns, sorted/filtered products)
54 Container (product card)
55 Column
56 Image (productUrl)
57 Text (name)
58 Text (price, bold)
59 Row (rating stars + category chip)

Common mistakes when implementing Dynamic Sorting and Filtering in a FlutterFlow E-Commerce App

Why it's a problem: Ordering by rating while filtering by price range without handling the Firestore constraint

How to avoid: Detect the conflict: when an inequality filter is active on one field and sort is on a different field, fetch with the required orderBy and re-sort client-side using a Custom Function.

Why it's a problem: Not creating composite indexes for common filter-sort combinations

How to avoid: Create composite indexes in Firebase Console for every filter-sort combination you support. Check the Firestore error log for missing index suggestions.

Why it's a problem: Fetching all products and filtering entirely on the client

How to avoid: Use Firestore server-side filtering for the heavy lifting (category, price range, stock) and only fall back to client-side for the sort when Firestore constraints prevent it.

Best practices

  • Use Firestore server-side filtering for category and equality filters to reduce data transfer
  • Fall back to client-side sorting only when Firestore orderBy constraints conflict with filters
  • Create composite indexes for common filter and sort combinations
  • Show active filters as removable chips so users can see and modify their criteria
  • Display the results count to give users feedback on filter effectiveness
  • Add an empty state with a clear filters call-to-action when no products match
  • Limit client-side fallback to fetching at most 100 pre-filtered results for performance

Still stuck?

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

ChatGPT Prompt

I want to build a dynamic sorting and filtering system for a FlutterFlow e-commerce app. Products can be sorted by price, rating, or date, and filtered by category, price range, and stock status. Firestore has constraints on combining inequality filters with orderBy on different fields. Show me how to compose queries dynamically and fall back to client-side sorting when needed.

FlutterFlow Prompt

Create a product listing page with a sort dropdown and direction toggle at the top, category filter chips, a price range slider, an in-stock toggle, active filter chips with remove buttons, and a product grid below.

Frequently asked questions

How do I add text search to the sort and filter system?

Add a search TextField that updates a Page State searchText. Use Firestore prefix query (name >= searchText) for basic search, or integrate Algolia via FlutterFlow's built-in Algolia Backend Query for full-text search with typo tolerance.

Can I save user filter preferences for next visit?

Store the filter state in App State with persistence enabled. On page load, initialize Page State from the persisted App State values so users return to their preferred filter settings.

How many composite indexes do I need?

One per unique filter-sort combination. With 5 categories, price filter, and 4 sort options, you may need 10 to 15 indexes. Firestore allows up to 200 composite indexes per database.

What if I need to filter by multiple categories at once?

Use whereIn for up to 10 categories or whereArrayContainsAny if products have a categories array field. For more than 10, batch into multiple queries and merge results.

How do I handle pagination with dynamic sort and filters?

Use Firestore query cursors with startAfterDocument. When the sort or filter changes, reset the cursor and load from the beginning. FlutterFlow's Infinite Scroll handles this when properly configured.

Can RapidDev build advanced filtering for my e-commerce app?

Yes. RapidDev can build sophisticated filter systems with multi-faceted search, Algolia integration, saved filter presets, and optimized Firestore query composition.

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.