Bubble Docs
  • Introduction
  • New? Start Here
  • What is Bubble?
  • The Glossary
  • User manual
    • Getting started
      • What is Bubble?
      • Building your first app
        • Planning features
        • Database structure
        • Design and UX
        • eCommerce and payments
          • Shopping cart
          • Checkout page
          • One-time payments
          • Subscriptions
          • Marketplace
      • Creating and managing apps
      • The Bubble editor
        • Tabs and sections
          • Design tab
            • The element tree
            • The property editor
          • Workflow tab
          • Data tab
          • Styles tab
          • Plugins tab
          • Settings tab
            • Application settings
              • Custom headers/body
              • Visual settings
              • Social media sharing
              • Translating your app
              • Email settings
              • Collaboration
            • Custom domain and DNS
          • Logs tab
        • Tools
          • Key features
          • The search tool
          • The Issue Checker
          • The element tree
          • The element property editor
          • The debugger
          • Notes
        • Previewing your app
      • Transitioning to Bubble from...
        • JavaScript
        • HTML and CSS
        • SQL
    • Design
      • Elements
        • The element hierarchy
          • The element tree
        • The page
        • Containers
          • Groups
          • Repeating groups
          • Table elements
          • Popups
          • Floating groups
          • Group focus
        • Visual elements
        • Input forms
          • Text and numbers
          • Dates and time
          • File uploads
          • Selection controls
        • Reusable Elements
      • Styling
        • Color variables
        • Font variables
        • Styles
        • Custom Fonts
      • Responsive design
        • Building responsive pages
        • Legacy articles
          • The Basics (Legacy)
          • Building Responsive Pages (Legacy)
          • Migrating Legacy Pages
          • Tips When Designing (Legacy)
      • Templates
      • The Component Library
      • Importing from Figma
    • Data
      • The database
        • Data types and fields
        • Creating, saving and deleting data
        • Finding data
        • Displaying data
        • Protecting data with privacy rules
        • The database editor
        • Export/import data
          • Exporting data
          • Importing data (CSV)
        • Working with location data
        • Using Algolia
        • Database structure by app type
          • Marketplace Apps
          • Directory & Listings Apps
          • Social Network Apps
          • SaaS Apps
          • Project Management Apps
          • CRM Apps
          • Professional Services Apps
          • On-demand Apps
          • Documentation/ CMS Apps
          • Applicant Tracking System (ATS) Apps
          • Portfolio Apps
          • Gallery Apps
          • Online Store / Ecommerce Apps
          • Blog Apps
          • Messaging App
          • Dashboards
          • Building Block Apps
          • Bubble as a backend
      • Files
      • Images
      • Static data
        • App texts (translations)
        • Option sets
      • Temporary data
        • Custom states
        • URL parameters
      • User accounts
        • Authentication plugins
          • Facebook plugin
          • Fitbit plugin
          • Google plugin
          • Instagram plugin
          • LinkedIn plugin
          • Pinterest plugin
          • Slack plugin
          • Wistia plugin
          • YouTube plugin
        • Cookies set by Bubble
      • Time, dates and time zones
    • Logic
      • The frontend and backend
      • Workflows
        • Events
          • Frontend events
            • Recurring workflows
            • Custom events
          • Backend events
            • Database trigger events
        • Actions
        • API Workflows
      • Dynamic expressions
      • Conditions
      • Navigation
        • Single-page applications (SPA)
        • Multi-page applications
        • Page slugs
    • Workload
      • Understanding workload
        • Activity types
        • The workload calculation
        • Client-side and server-side processing
      • Tracking workload
        • Measuring
          • Using App Metrics
        • Monitoring
          • Workload notifications
          • Infinite recursion protection
      • Optimizing workload
        • Optimization framework
        • Optimization checklist
          • Page load
          • Searches
          • Workflows and actions
          • Backend workflows
        • Agency showcases
          • Minimum Studio
          • Neam
          • Support Dept
    • Security
      • Bubble's security features
      • Planning app security
      • Client-side and server-side
      • Bubble account security
      • App security
      • Page security
      • Database security
      • API security
        • API Connector security
        • Data API security
        • Workflow API security
      • Flusk
        • Overview
        • Flusk plan features
        • Getting started with Flusk
        • Flusk security tools
          • The Issues Explorer
          • Issue details
          • Tools and settings
            • Pages rating
            • Database rating
        • Flusk FAQ
      • Cookies
      • Security checklist
    • Publishing your app
      • Web app
      • Native mobile app
        • Global native mobile settings
        • iOS App Store
        • Google Play Store
        • Publishing FAQ
    • AI
      • Generate apps with AI
        • About AI app generation
      • AI page designer
      • Connect to AI agents
    • Maintenance
      • Collaborators
      • Version control
        • Best practices: Version control
        • Transitioning from the legacy version control
        • Terminology: Version control
        • Version Control (legacy)
      • Commenting
      • Database maintenance
        • Copying the database
        • Restoring database backups
        • Bulk operations
          • Bulk operation methods compared
        • Wiping change history
      • Performance
        • Hard limits
        • Capacity Usage (legacy)
        • Notes on queries
      • SEO
        • Introduction to SEO
        • SEO: App
        • SEO: Page
      • Testing and debugging
        • Introduction to testing and debugging
        • The debugger
        • The server logs
        • Supported browsers
      • API workflow scheduler
    • Integrations
      • API
        • Introduction to APIs
          • What is a RESTful API?
        • The Bubble API
          • Bubble API terminology
          • Authentication
            • How to authenticate
            • No authentication
            • As a User
            • As an admin
          • The Data API
            • Data API Privacy Rules
            • Data API endpoints
            • Data API requests
          • The Workflow API
            • Workflow API privacy rules
            • Workflow API endpoints
            • API workflows
              • Creating API workflows
              • Scheduling API workflows
              • Recursive API workflows
              • API Workflow Scheduler
              • Case: Stripe notifications
        • The API Connector
          • Authentication
          • API Connector security
          • API guides
            • OpenAI
              • Authentication
              • Calls
                • ChatGPT
                  • Chat
            • Google Translate
              • How to setup Google API keys
          • Streaming API
        • API security
        • Plugins that connect to APIs
        • API Glossary
      • Plugins
        • What Plugins Can Do
        • Installing and using Plugins
        • Authentication plugins
        • Special Plugins
      • SQL Database Connector
      • Bubble App Connector
      • WorkOS
        • WorkOS SSO
        • WorkOS API
    • Infrastructure
      • Sub-apps
      • Bubble release tiers
      • Hosting and scaling
        • How Bubble hosting works
        • Scaling with Bubble
        • CDN (Cloudflare)
        • Bubble app names
        • Domain and DNS
      • Compliance
        • GDPR
        • SOC 2 Type II
        • HIPAA
        • Other frameworks and standards
    • Bubble for Enterprise
      • Hosting and infrastructure
        • Dedicated instance
          • The Dedicated editor experience
          • Technical specs
          • Main cluster dependencies
          • Customizable options
          • Migration process
            • Pre-migration
            • During migration
            • Post-migration
      • Security and compliance
        • Single sign-on (SSO)
        • GDPR
        • SOC 2 Type II
        • HIPAA
        • Other frameworks
        • Bubble's security features
      • Admin and collaboration
      • Priority support
      • Billing and Payment Guideline for Dedicated Instances
  • Core Reference
    • Using the core reference
    • Bubble's Interface
      • Design tab
      • Design tab (Legacy)
      • Workflow tab
      • Data tab
      • Styles tab
      • Styles tab (Legacy)
      • Plugins tab
      • Settings tab
      • Logs tab
      • Template tab
      • Toolbar
      • Top and context menu options
      • Deployment and version control
        • Deployment & Version Control Dropdown (legacy)
      • Notes
    • Elements
      • General properties
      • General properties (Legacy)
      • Styling properties
      • Styling Properties (Legacy)
      • Responsive Properties
      • Responsive Properties (Legacy)
      • Conditional formatting
      • States
      • Page Element
        • Page Element (Legacy)
      • Visual Elements
      • Containers
      • Container Layout Types
      • Containers (Legacy)
      • Input Forms
      • Reusable Elements
      • Element Templates (legacy)
    • Workflows
    • Events
      • General events
      • Element events
      • Custom events
      • Recurring event
      • Database trigger event
    • Actions
      • Account
      • Navigation
      • Data (things)
      • Email
      • Element
      • Custom
    • Data
      • Data Sources
      • Operators and comparisons
      • Search
      • Privacy
    • Styles
    • API
      • The Bubble API
        • The Data API
          • Authentication
          • Data API endpoints
          • Data API requests
        • The Workflow API
      • The API Connector
        • Authentication
        • Adding calls
    • Bubble-made Plugins
      • AddtoAny Share Buttons
      • Airtable
      • API Connector
      • Blockspring
      • Box
      • Braintree
      • Bubble App Connector
      • Chart.js
      • Circle Music Player
      • Draggable Elements
      • Dropzone
      • Facebook
      • Fitbit
      • Full Calendar
      • Google
      • Google Analytics
      • Google Optimize
      • Google Places
      • Ionic Elements
      • iTunes
      • Slidebar Menu
      • LinkedIn
      • Localize Translation
      • Mixpanel
      • Mouse & Keyboard Interactions
      • Multiselect Dropdown
      • Progress Bar
      • Rich Text Editor
      • Rich Text Editor (Legacy)
      • Screenshotlayer
      • SelectPDF
      • Slack
      • Segment
      • Slick Slideshow
      • SQL Database Connector
      • Star Rating
      • Stripe
      • Tinder-like Element
      • Twitter
      • YouTube
      • Zapier
    • Application Settings
      • App plan
      • General
      • Domain / email
      • Languages
      • SEO / metatags
      • API
      • Collaboration
      • Sub-apps
      • Versions
  • Account & Marketplace
    • Account and billing
      • Pricing and plans
        • Plans and billing
        • Billing cycle
        • FAQ: Pricing and Workload
      • Account Management
      • Building Apps for Others
      • Selling on the Marketplace
      • Plans & Billing (legacy)
    • Official Bubble Certification
      • Hiring certified developers
    • Building Plugins
      • The Plugin Editor
      • General Settings
      • Updating to Plugin API v4
      • Adding API Connections
      • Building Elements
      • Building Actions
      • Loading Data
      • Publishing and versioning
      • Github Integration
    • Building Templates
    • Application and data ownership
    • Marketplace policies
    • Bug reports
  • Vulnerability Disclosure Policy
  • Beta features
    • About the Beta features section
    • Native mobile apps 🔒
      • Introduction
        • What is a native mobile app?
        • Native mobile vs. web development
        • Differences in native and web elements
        • Native mobile app terminology
      • Building
        • Views and navigation
        • Native mobile actions
        • Components and gestures
        • Device resources
          • Location services
          • Camera/photo library
      • Previewing
      • Publishing
Powered by GitBook
On this page
  • How dynamic expressions are structured
  • Data sources
  • Operators
  • Comparisons
  • Adding Dynamic expressions
  • Expression use cases
  • In elements
  • In conditions (conditional expressions)
  • In workflows
  • Checking the value of an expression step
  • Copy/pasting expressions
  • Copy one expression
  • Copy all content in a field
  • How expressions are processed

Was this helpful?

  1. User manual
  2. Logic

Dynamic expressions

This section covers how to set up dynamic expressions in Bubble

Last updated 9 months ago

Was this helpful?

In this article we'll be diving into the world of dynamic expressions.

Dynamic expressions are like "live" formulas that update in real-time based on user input, database updates and other changes in your app.

Dynamic expressions are one of Bubble's basic building blocks and are used in a wide range of scenarios.

For example, let's say you're building an app that tracks customer orders. You might use a dynamic expression to calculate the total cost of an order, based on the price of each item and the quantity ordered. Or you might use a dynamic expression to automatically update inventory levels when a new order is placed.

Like formulas in a spreadsheet, dynamic expressions in Bubble update in real-time based on changes in your app and database. So if a customer changes the quantity of an item in their order, the total cost of the order will automatically update.

By mastering dynamic expressions, you'll be able to create powerful, interactive apps that are constantly kept in sync with relevant data.

How dynamic expressions are structured

Although dynamic expressions can vary greatly in complexity, they essentially consist of three main components: data sources, operators and comparisons.

Data sources

A data source is any place from which Bubble can retrieve data, such as:

  • A

  • The

  • An

  • An

  • The current date/time

  • The user's

This is not an exhaustive list, but it illustrates the point that data sources are not just database records, but any channel from you can draw some sort of information. Expressions always start with a data source, and you and then (often optionally) add one or more operators to that data source to transform, aggregate or manipulate the data in some way.

Operators

Operators are all kinds of functions or actions that can be performed on the data source, such as filtering, sorting, grouping, aggregating, reducing, joining, and many others, depending on the data type you are working on.

As we saw in the example from earlier, the dynamic expression goes through two steps, separated by a colon (:):

  1. Data source: we are using the Do a search for data source to search for users

  2. Operator: we added the count operator to the search to instruct Bubble to count the results

An expression will always return the value of its last step. As such, the expression above would not return a list of users, but a number representing the count of users (such as 50).

Data-specific operators

Bubble will adjust the list of available operators based on what kind of data the data source returns. In the example above, the data source searches for users and returns a list. Since this is a quantifiable resource, we can instruct Bubble to count the number of entries in the list.

Were we to change the data source to another type of data, such as a date, the list of available operators changes to reflect it:

An operator will in many cases change the format of the data returned. Let's look at the two examples in the above screenshots:

  • In the first we are using an operator to count the results of a search, and the data switches from a list of database records to a number

  • In the second, we are looking at a , and the returned data depends on the operator:

    • The formatted as 3/10-23 operator will turn the datetime into a text string such as "3/10-2023".

    • The < -range - > will turn two datetimes into a

    • The +seconds/+ minutes etc operators will add the number of seconds and minutes but keep the datetime format

Comparisons

Comparisons are the third component of an expression and are used to compare two values to reach a value that is either yes or no. You can see comparisons as a sort of question. In the two examples below, we first see how a human would read the question, and then how it would be formatted in an expression.

Is 5 a bigger number than 3? Aswer: yes

This is how a human being would ask the question, and it's not open-ended: the answer will always be yes. In an expression, the same question would be laid out more mathematically and always have a clear answer:

5 > 3 = yes

The > symbol represents bigger than, and again the answer would be yes.

In these two examples, 5 and 3 are both data sources, and the > is the comparison. As such, we are comparing the value of two data sources to get to a yes or no (or true/false if you will).

Expressions are set up to work with dynamic data sources and operators, so let's compare two numbers in an expression that are the results of counting things. In our earlier example, we counted the number of users. Let's assume we have another data type called Task and compare how many there are of each.

The structure in this expression will be:

Data source:operator comparison data source:operator
Search for users:count is search for tasks:count

We are replacing the > with an is. In other words, we are not asking is one bigger, but changing the question to are they the same. This is what that looks like in an expression:

Let's assume we have 50 users and 20 tasks, in which case the question we ask is:

Is 50 the same as 20? Answer: No

Comparing other types of data

Comparisons can handle any type of data as long as they can be compared. For example, we could ask the question:

Is London the same as New York? Answer: No

In this example we're no longer looking at numbers, but comparing two strings of text. Since the two strings are not identical, we can conclude with the answer no. In a Bubble expression we might get those names from a data type called City, looking something like this:

In the expression above, we are combining multiple data sources, operators and a comparison to ask the question:

Is the name of the City saved on the current user the same as the name of the first city returned by this search? Answer: no

In this example we compared the names of the city (text) specifically, but we could also ask Bubble directly whether the two cities are indeed the same database record:

The question has now changed to:

Is the database record saved in the City field of the user the same as the dataase record found with this search? Answer: No 

The two examples would yield the same result: no, they are not the same. However, if the two cities shared names (such as Paris in the US state of Texas and Paris the capitol of France), the first one would respond with yes and the second would respond with no: they have the same name, but they are not the same database record.

As we can see from that example, you should put some thought into comparisons to make sure that they can reliably give the right response.

Adding Dynamic expressions

Dynamic expressions can in many cases be mixed in with regular text to produce a coherent message to your users. In the example above for example, we set up a dynamic expression to count the number of users, and wrapped the expression in a text:

There are [expression] users in your app

To your users, the full text will simply be: "There are 50 users in your app", hiding the calculation going on under the hood.

To add an expression anywhere in a text field, set focus to that field and then click the Insert dynamic data button that shows up next to it.

Sometimes there will be a field with an empty expression.

  • To create an expression there, simply click on it

  • To delete it, click on it and then click backspace

Expression use cases

Expressions, being such a central part of the Bubble platform, are used in a wide range of different scenarios. Let's look at a few:

In elements

Dynamic expressions can be used in to provide a value. We have already looked at how we can place it in a text element to display the result of the expression as a text.

Example 1: Set an initial date

In the example below we are using an expression to set the initial value of a :

The initial content field tells Bubble to show a date in the element when the page loads. In a humanly readable sentence, we are telling Bubble:

Set the initial content of this Date/time picker element to the current date and time, but add one day

The result for the user would be that the default value of the element is at the current time tomorrow.

Example 2: Load a list of users and show them in a repeating group

When using a , we need to provide a data source, and this too is done by setting up an expression. For this, we could simply define a data source such as Do a search for Users, but to show how we can use expressions to be more complex, let's include an operator as well:

In this example we are using the operator to generate a list of users thats different than what we would get in the data source alone. In a humanly readable sentence, we are telling Bubble:

Search for one set of users and a second set of users and then return the list of users who are in both lists

If we assume that the two searches produce different results by having different constraints, we would be left with the list of users that are present in both of the search results.

In conditions (conditional expressions)

Conditions, or conditional expressions, are expressions that are set up to return a value that's either yes or no and then use that answer to either do something or not do it:

This can be used to:

  • Style an element depending on whether the condition is true

  • Trigger a workflow to run whenever the condition is true

  • Ask whether a workflow/action triggered somewhere else should run

Example 1: hide an element if the user isn't logged in

For our first example, we'll place a condition on an element that will hide the element if the user is logged out. For example, if we have a Sign out button, it makes sense to hide it.

  1. The first part is the expression: we use the data source current user and the operator is logged out to get a yes/no anwer

  2. We instruct Bubble to change one of the element's properties: we set this element is visible to unchecked.

In a humanly readable sentence, we are saying:

If the current user is logged out, make this button invisible

Example 2: stop a workflow from running

In the second example, we'll look at how a conditional expression can determine whether a workflow should run or not when it's triggered. Let's say we have a form where users can create a new Task, but we don't want to create the contact if the user hasn't provided a name for the task:

In this example, the data source is the input element Input task and we've added two operators:

  • value instructs Bubble to return the value from that input (which would be the task name the user has provided)

  • is not empty gives us a yes/no answer to whether the value operator returns an empty result or not

In a humanly readable sentence, we are saying:

Only run this workflow if the user has provided a name for the new task

In workflows

We can also use expressions in workflows to produce a particular result.

Example 1: saving aggregated data

Let's say that we run an app where users provide reviews for different products. In addition to the built-in user data type, we have a custom data type called Review which includes a number field where users give a score between 1-10.

As the user keeps adding reviews, we want to save their average score on their profile. Let's see how expressions can do that.

  1. We have workflow that makes changes to the current user, and we've set it to make a change in a field called Average score

  2. We then add the data source Search for users and we add a constraint that the Review must have been created by the data source This user.

  3. We add the operator each item's Score which changes the result from a list of Reviews to a list of numbers (the score from each review)

  4. Lastly, we add the average operator, which takes a list of numbers and calculates the mean value. The data type in the end is a number which is what the Average score field on the user expects

In a humanly readable sentence, we are saying:

Save the average score to the user by searching for all the users review and calculating the mean

Example 3: creating a date range from two date values

A date range is a piece of data that provides a range between to by storing a start and end. They simplify the process of determining if a datetime falls within a specific range, among other uses.

Let's say we have system where users can pick a start and end date for a vacation, and we want to turn that into a date range and store it in a .

We'll use the value of the two date pickers as the data sources, and combine them using the < - range - > operator.

  1. The first field is the element where we store the custom state – in this case we chose the page itself (index)

  2. Then we choose the custom state. We created one and named it Date range.

  3. Then we generate the date range by using the < - range - > operator.

Checking the value of an expression step

Every expression consists of steps, and each of those steps return a value. Each of those values will be of a specific type, such as a yes/no, a number, a text or a custom data type.

In complex expressions, it can be challenging to keep track of what kind of value is returned by each step. To see the type of data, simply hover the step with the mouse pointer:

Copy/pasting expressions

There are two ways in which you can copy and paste expressions:

Copy one expression

The first way is to copy a single expression. To do that, right-click the expression and pick Copy expression.

Note that to paste expressions, you need to right-click an area that accepts an expression. You may need to click the Insert dynamic data link.

Copy all content in a field

If you want to copy not just one expression, but all content of a field, you can right-click outside of the expression but still inside the input field. Note that this will copy both the expression and regular text:

To paste it, you need to click inside of a field that accepts it, but not on an expression.

How expressions are processed

Dynamic expressions are evaluated from left to right, which means that the system reads each part of the expression in order, one at a time, starting from the leftmost component and moving towards the right. This is different from the mathematical convention used in many other programming languages, which evaluates expressions based on the order of operations, such as parentheses, exponents, multiplication and division, and addition and subtraction.

This left-to-right evaluation order can sometimes lead to unexpected results if you are used to other programming languages, so it's important to keep in mind when writing expressions in Bubble. However, it can also make expressions easier to read and understand, since they are evaluated in a more intuitive way that matches the way we typically think about expressions in everyday language.

Here we describe what operators are in general. If you want the list and technical documentation on each operator, you may be interested in checking out the core reference entry on operators. Reference:

In this section we briefly explore how conditions work. If you are interested in learning more you can check out our dedicated article on the subject: Article:

In this section we briefly explore how workflows work. If you are interested in learning more you can check out our dedicated article on the subject: Article:

Data source

A data source is any place from which Bubble can retrieve data, such as the database, the current user or an API.

Operators

Operators functions or actions that can be performed on the data source, such as counting, sorting and calculating.

Comparisons

Comparisons let you compare two compatible values, such as two numbers, data types or strings of text and get a yes/no result

Operators
Conditions
Workflows
Expression lets you work with data dynamically and in many different ways. In the example above we are searching for users in the database and counting them. The result would be a live reflection of the count of users that updates automatically every time a user is added or removed.
Bubble will list the operators that are relevant for the type of data returned by the data source. In this example the data source is Search for users (which returns a list of database records) and we can select different operators that apply to that data type.
In this example we've changed the data source to one returning a datetime, and Bubble changes the list of available operators to reflect it.
1) Set focus to the text field, and then 2) click the Insert dynamic data button to create an expression where the insertion point is.
The Click text indicates that Bubble is already expecting an expression.
Click the image to enlarge.
Hovering a step in an expression will reveal the type of data that step returns.