Transcript
So to understand what a custom state is, let's sketch out here what we're actually trying to do.
Our current scenario is where we have this selectable list element. In this selectable list element, we have some trip types: trip type A, trip type B, trip type C. What we also have is a list of trips.
Now, this selectable list element has a special property, a special value, a special output, and that is what we're calling, or what Bubble is calling, the selected choice. The value of this selected choice changes depending on what the user taps on, what the user selects from this selectable list.
If they click on trip A, then trip A becomes the selected choice. And of course, what's happening is that this selected choice is being watched. It's being watched by this list of trips, and the value in this selected choice specifically is being used as part of a filter, as part of a search constraint.
What that means is that as this value changes — let's say that the user selects trip type B — the list of trips reacts in real time. We might lose a couple of trips from the data source here. Or maybe the user selects trip C. Then in real time, the trips that appear in this list are going to react.
There is this real-time synchronous relationship between this value (the selected choice) and the entries inside this list of trips.
But now let's paint a slightly different picture.
Here's our selectable list just like before. It has a selected choice value. And then, just like before, we also have a list of trips. But we also have the addition of this strange little trip-shaped container in the middle.
We’re going to have a little button. What's going to happen is this: the user chooses some option in the selectable list, which enters the selected choice output for this element. But it just sits there. Our list of trips is not going to be watching the selected choice output anymore. Instead, it's going to be watching this little container.
By default, this little container is empty. There is nothing in it until the user hits this button. Once they hit the button, the value from the selected choice is populated in that container.
So what this means is that we now have granular control. It's not just electricity coming into a house that turns a light on — we have a light switch in the middle. The user can play around with different values in the selected choice, and the list of trips doesn’t care. Only when the user hits this button does the selected choice move into the container, and then the list of trips reacts.
This little container is what we call a custom state. It’s a bureaucratic name for what is essentially just a container for data. A group can also hold data. If you know programming, a custom state is essentially a temporary variable, a temporary holding pen for data so we can reference and use it in different parts of the app.
We’re going to set this up now. There are many ways to use custom states, and they are a very important part of a Bubble developer’s toolkit.
Right now, when a user selects a filter, that filter is automatically applied. So that workflow is triggered when a selectable list item is clicked.
Let's remove this workflow condition by hitting the three dots on the workflow and deleting the workflow entirely.
Now, we need to create our custom state. A custom state is attached to an existing element within our view. You can think of it as a little backpack that an element can wear.
We can create a custom state on the trips view, but best practice is to set it at the level of the module it relates to. In our case, this is the sheet filters module.
Click the little eye icon, add a new custom state. Give it a name: filter_trip_type
. Then set its type — it can be any basic type, a data type, or in our case, an option set. We'll select trip type
.
You can add a default value if you want, but we won't here.
To push data into this custom state, we need a button in the filters sheet (like Apply Filters). Add margin as needed, then create a workflow: Element Actions → Set State of an Element.
Element:
sheet filters
Custom State:
filter_trip_type
Value: the selected choice from the selectable list trip filter
Also, hide the sheet after the user hits the button.
To verify, add a text element to display the value of the custom state. Reference the element that has the custom state (sheet filters) and display the value. By default, it’s empty. Select a value and hit apply — it updates correctly.
Next, feed this custom state into the search constraints of the trips list.
Add a constraint on the trip type field.
Use the value from the custom state in the sheet filters instead of the selectable list.
Test: choose a filter, hit apply, trips list updates accordingly.
Hook up the Clear button:
Current workflow clears the selectable list.
Also clear the custom state by adding a workflow action: Set State → Value: empty.
After clearing, the trips list behaves as if no filter is applied.
This UX is helpful when there are multiple filters.
Date Filters
Add two date pickers inside a group (
group dates
).Add two new custom states:
filter_date_from
andfilter_date_until
(type: date).Apply Filters workflow: set custom states from the date picker values.
Add constraints to the trips list:
start date >= filter_date_from
end date <= filter_date_until
Test: select dates, hit apply, trips list updates accordingly.
UX Tweaks
Show previously selected values when reopening the sheet:
Use workflow Do when condition is true → sheet filters is visible
Action: Reset Group → values reset to initial content (custom states)
Clear all filters:
Clear trip type,
filter_date_from
,filter_date_until
Empty States:
If trips list empty AND all filters empty → show “you haven’t added any trips yet”
If trips list empty AND any filter has a value → show “no results”
Hook up the second clear filters button (for empty state) to clear custom states too.
That’s custom states in Bubble: temporary data containers that allow controlled filtering, multiple filters, reset behavior, and proper empty state handling.
Next lesson: deleting multiple diary entries at once.