Build an advanced multi-filter search in Bubble that combines text input, dropdown filters, date range selectors, and sorting options to query a single Repeating Group in real time. This tutorial walks through setting up compound search constraints that update results instantly as users adjust any filter.
Overview: Building a Complex Search in Bubble
Simple keyword search is often not enough. Users need to filter by category, status, date range, and then sort the results. This tutorial shows how to build a single search interface that combines all these filters into one query on a Repeating Group, updating results in real time without requiring a search button.
Prerequisites
- A Bubble app with at least one Data Type containing 10+ records
- Basic understanding of Repeating Groups and Do a search for
- Familiarity with the Design and Workflow tabs
Step-by-step guide
Set up the filter UI elements
Set up the filter UI elements
On your search page in the Design tab, add a Row group at the top. Inside it, place a Search Input for text search, a Dropdown for category (data source: your category Option Set), a Dropdown for status filter, two Date Picker elements for start and end date, and a Dropdown for sort order with options like Newest First, Oldest First, A-Z, and Z-A. Arrange them in a single row with appropriate spacing.
Expected result: A filter bar with text search, category dropdown, status dropdown, date range pickers, and sort dropdown.
Configure the Repeating Group with compound constraints
Configure the Repeating Group with compound constraints
Below the filter bar, add a Repeating Group. Set its Type of content to your Data Type. Set the data source to Do a search for with these constraints: title contains Search Input's value (check Ignore empty constraints), category equals Dropdown Category's value (check Ignore empty constraints), status equals Dropdown Status's value (check Ignore empty constraints), Created Date is greater than or equal to Date Picker Start's value (check Ignore empty constraints), Created Date is less than or equal to Date Picker End's value (check Ignore empty constraints).
Pro tip: Always check Ignore empty constraints on every filter constraint. When a filter is empty, that constraint is skipped and all matching records are returned.
Expected result: The Repeating Group displays records that match all active filters and shows everything when all filters are empty.
Add dynamic sorting with conditional data sources
Add dynamic sorting with conditional data sources
You cannot dynamically change sort order on a single data source. Instead, use conditional data sources on the Repeating Group. Add a conditional: When Dropdown Sort's value is Newest First, set data source to the same search sorted by Created Date descending. When Oldest First, sort by Created Date ascending. When A-Z, sort by title ascending. Each conditional uses the same search constraints but different Sort by values.
Expected result: Selecting a sort option re-sorts the Repeating Group results without losing the active filters.
Display results with empty state handling
Display results with empty state handling
Inside the Repeating Group cell, display the key fields: title, category, status badge, and date. Add a Text element below the Repeating Group showing No results found with a conditional: This element is visible when the Repeating Group's list count is 0. This gives users feedback when their filters are too narrow.
Expected result: Search results display with relevant information and a no-results message appears when filters return zero matches.
Add a Clear Filters button
Add a Clear Filters button
Add a Button labeled Clear Filters next to the filter bar. Create a workflow: When Button Clear Filters is clicked, use the Reset relevant inputs action. This resets all inputs on the page to their default empty state. Because Ignore empty constraints is enabled, clearing all filters returns all records.
Expected result: Clicking Clear Filters resets all filter inputs and shows all records in the Repeating Group.
Optimize search performance for large datasets
Optimize search performance for large datasets
If your Data Type has thousands of records, avoid using the :filtered operator after the search — it runs client-side and is slow. Keep all filtering in the Do a search for constraints, which run server-side. Limit the Repeating Group to 20 items per page with pagination. For text search across multiple fields, consider creating a search_text field that concatenates title and description.
Pro tip: For very large datasets (10,000+ records), consider the OmniSearch plugin which connects to Algolia or Typesense for blazing-fast full-text search.
Expected result: Search results load quickly even with thousands of records by using server-side constraints and pagination.
Complete working example
1COMPLEX SEARCH — WORKFLOW SUMMARY2==================================34PAGE ELEMENTS5 Row: Filter Bar6 - Search Input (text): keyword search7 - Dropdown Category: Option Set or Data Type8 - Dropdown Status: Option Set9 - Date Picker Start: start date filter10 - Date Picker End: end date filter11 - Dropdown Sort: Newest, Oldest, A-Z, Z-A12 - Button: Clear Filters1314 Repeating Group: Search Results15 Type: Product (or your Data Type)16 Data source: Do a search for Products17 - title contains Search Input value18 [x] Ignore empty constraints19 - category = Dropdown Category value20 [x] Ignore empty constraints21 - status = Dropdown Status value22 [x] Ignore empty constraints23 - Created Date >= Date Picker Start value24 [x] Ignore empty constraints25 - Created Date <= Date Picker End value26 [x] Ignore empty constraints27 - Sort by: Created Date, descending2829 Conditional data sources on RG:30 When Sort = Newest First:31 Same search, Sort by Created Date desc32 When Sort = Oldest First:33 Same search, Sort by Created Date asc34 When Sort = A-Z:35 Same search, Sort by title asc36 When Sort = Z-A:37 Same search, Sort by title desc3839 WORKFLOW: Clear Filters40 Trigger: Button Clear Filters clicked41 Step 1: Reset relevant inputs4243 PERFORMANCE TIPS44 - All filters use server-side constraints45 - Pagination: 20 items per page46 - No :filtered operator on large datasets47 - Concatenated search_text field for multi-field searchCommon mistakes when creating a complex search function in Bubble.io: Step-by-Step Guide
Why it's a problem: Forgetting to enable Ignore empty constraints
How to avoid: Check the Ignore empty constraints checkbox on every optional filter constraint.
Why it's a problem: Using the :filtered operator instead of search constraints
How to avoid: Put all filter logic inside Do a search for constraints. Only use :filtered for complex expressions that cannot be expressed as constraints.
Why it's a problem: Not handling the empty results state
How to avoid: Add a No results found text element with a visibility condition based on the Repeating Group list count being 0.
Best practices
- Always enable Ignore empty constraints on optional filter parameters
- Use server-side search constraints rather than client-side :filtered for performance
- Paginate Repeating Groups to 20 items to reduce initial load time
- Create a concatenated search_text field for searching across multiple fields efficiently
- Show a result count above the Repeating Group so users know how many matches exist
- Add a loading indicator that shows while search results are being fetched
- Use Option Sets for filter dropdowns to ensure consistent values
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I need to build an advanced search page in Bubble.io with text search, category dropdown, status filter, date range picker, and sort options, all filtering a single Repeating Group in real time. How should I structure the constraints and handle empty filters?
Create a search page with a filter bar containing a text input, category dropdown, status dropdown, date range pickers, and sort dropdown. Below it, add a Repeating Group that updates in real time based on all active filters using Ignore empty constraints on every filter.
Frequently asked questions
Why do my search results disappear when I select a filter?
You likely forgot to check Ignore empty constraints on one of your other filter constraints. When any non-ignored constraint has an empty value, it returns zero results.
Can I search across multiple fields like title and description?
Yes. Create a search_text field on your Data Type that concatenates title and description. Then search against search_text contains instead of individual fields.
How do I make search case-insensitive?
Bubble's text contains constraint is already case-insensitive by default. Searching for 'apple' will match 'Apple', 'APPLE', and 'apple'.
What if I need full-text search with relevance ranking?
Bubble's native search is constraint-based, not relevance-ranked. For full-text search with ranking, use the OmniSearch plugin which connects to Algolia or Typesense.
Can I save user filter preferences?
Yes. Store the filter values in a custom state or URL parameters. For persistent preferences, save them as fields on the User data type and load them when the page opens.
Can RapidDev help optimize my search for a large database?
Yes. RapidDev can architect high-performance search systems in Bubble, including external search integration, query optimization, and caching strategies for databases with tens of thousands of records.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation