Most information that you will use in your Bubble application will be dynamic, and coming from the database, or from other sources of data, such as external APIs (plugins). In these cases, you will use the Expression Composer to define an expression that will be displayed as an expression in Edit-mode and evaluated in Run-mode. For instance you will see in the Editor 'Current user's email', which may become in Run-mode, depending on who is logged in, '[email protected]'.
The Expression Composer is a key element of the Bubble Application Editor that lets you build these expressions without typing anything, but instead by picking some options in some dropdown menus. The system will automatically prompt you in the next menu with options that are available given what you have selected so far. For instance, if the first main entry in the expression is 'Current User', the next menu will offer options such as 'is logged in', 'is not logged in', 'email', etc. In Bubble vocabulary, the main entry (i.e. the first choice in a dynamic expression) is known as a "data source" and all the chunks after it are known as "operators" (e.g. "email" in this case, or expressions like ":first", "contains", etc.).
The composer lets you build complex expressions by combining different sources of data. It is important to note that the evaluation happens from the left to the right, without parentheses priorities.
Expressions' types are evaluated in Edit-mode to validate the type consistency. For instance, if you are trying to display the Current User's email in a text element, 'Current User' won't be valid, as it is not a text, while 'Current user's email' will be valid. When an expression isn't valid, it will be reported as an issue in the Issue Checker and the whole expression will be displayed in red. The Run-mode debugger is very useful to understand how an expression is evaluated.
Data sources are where you get your data from when designing a dynamic expression. It is going to be the first section of the expression. Sources of data can be a search from the database, the current user, data from an external API, some page and browser information, etc.
Here are the key sources of data.
This data source lets you fetch entries of a given type from the database and returns a list of things. This can be used in repeating groups to display a list, to check the existence of some entries (by checking the length of the list), etc. A search is defined by a type of data to look for (for instance 'user', or 'car'), and optionally some constraints and sorts options.
You can define some constraints to narrow the search and only fetch items that meet these constraints. For instance, you may want to find 'cars' where the price is between two values. Defining a constraint works by picking the field you want the constraint to apply to, defining a comparison operator (such as =, <, >, contains), and then defining the value to be compared with, either a static value or a dynamic expression. A search without constraints will return all the entries in the database of that type.
You can either search by field, or do an all-field search. In such a case, the Search Engine will retrieve all entries that contain the text define as the value for the constraint.
When an expression is evaluated to an empty value, the constraint can be ignored, by design. To do so, check the box for 'Ignore empty constraints'. This is helpful when building filters into your design for your users. For instance, let's say we are performing a search on a page for cars, and you let users type a maximum price in an input. If you are using the value of this input in a search constraint on the price field, and if the user has not typed anything, all cars will be retrieved (instead of returning no cars).
The 'Get Data from API' data source lets you fetch data from an external service or server and returns a list of objects of that type. If you add some plugins to your app that offer some data sources, you will see some options in the dropdown for the API provider.
Each API has different parameters, and the User Interface will prompt you to enter the relevant values. For instance, the Google Places API will need you to enter a value for what you're looking for ('cafe', 'restaurant', etc.) and an address. Here again, as you would do in a search, you can use dynamic expressions to make these API parameters dynamic.
The current user represents the currently logged in user. This gives you access to the different fields that are defined on the user type, in addition to the few built-in fields.
In workflows, when an action returns some data, you will often want to access the result of the previous operation in the subsequent actions. For instance, an action may create a thing of type 'order', and you need to get the ID of this thing to send it in an email. The 'Result from Previous action' data source lets you do this.
This is one of the most common data sources. In Bubble, container elements can have a thing attached to them, so that all elements inside can access this thing. You can control which thing a group has in its context by modifying the data source field or by using a 'Display data in group' action. A repeating group functions in a similar way. Each cell will have a thing in its context that can be accessed as a data source.
Bubble has a few operations that can be applied to lists. In particular, you can apply sorting and filtering to a list of things. These are different from search constraints as they are evaluated after the list is retrieved from the database, and therefore can lead to slower performance.
Editing dynamic expressions happens through the subsequent dropdown menus. You can use your mouse to pick the right option, and can also use the keyboard. Pressing the arrow keys lets you navigate the options, while pressing 'delete' will go back up in the expression and delete the subsequent entries.
Bubble also has a few tools that help manipulating long expressions. You can find them with the contextual menu, but right clicking on an expression. In particular, you will be able to copy/ paste expressions, insert some dynamic expressions if you are working on a text expression with some dynamic entries, and reveal the element or the action an expression is referring to (if any).