Programming Design Patterns

I’m still relatively new to Bubble, but not entirely new to programming.

I have learned some strategies for variables (hidden popup that has a group of type “thing” that can hold onto data) and functions (reusable elements that are generalized to accept expected input and produce an output).

I’m wondering if there is a resource for additional, and more advanced, design patterns in Bubble. Any resources you can point me to would be greatly appreciated!

Thank you.

1 Like

Even if you’re an experienced programmer in other languages/environments it is worth doing the Bubble Lessons and Tutorials and at least watching (if not following along with) the “Crash Course” videos. Find all that here: Academy | Bubble

Bubble is essentially a full-stack web development environment (but with a visual programming paradigm) and all of the underlying technologies are the same as in any other web dev environment: HTML, JavaScript, and CSS (and the Bubble database, of course).

Here’s a handful of not exactly “design patterns”, but more basic things that are unique (or unusual) in Bubble that may not be obvious at first:

While you correctly note that Groups can hold some value, the fact that groups can hold data of some type is typically for allowing some value to “cascade” down the element tree for display in some sort of display element (a text, image, repeating group element, etc.).

More properly and generically, local variables held in memory are realized as “Custom States”. Such states can be put on any element and have no visual representation in the editor or runtime view. You can create them when building an expression with the Expression Builder or by clicking the (i) icon in the property inspector. (You will find much other useful information there as well.)

In this sense they are more akin to adding a property to an object in JavaScipt than to declaring a variable, though creating a new custom state can be thought of as variable declaration.

Option Sets can be thought of as environment variables or system constants (though Things can be used in this way as well).

Arrays in Bubble are known as “lists”. They are only one-dimensional and have a somewhat strange assortment of operators on them that (oddly and unfortunately) do not represent the entire class of Array methods available in JavaScript.

It’s worth noting that most list operators in Bubble do not operate in an array-like manner, but in a Set-wise manner. That is, they result in deduplication of duplicate values. Lists in Bubble should generally be thought of as Sets. (It is possible to have a list of values that contain duplicates (for example, if you have a List of Things that have a numeric field Number on them, the expression List of Things's Number will be an array of numeric values, some of which may be duplicates. However, operating on that list with any of the set-wise operators (which include the :plus item and :minus item operators) will cause that list to turn into a set.

Here’s an example. We have a list of random integers, now we :plus item 5 to it, attempting to push the value 5 on to the list results in the list being deduplicated and since 5 already exists in the list, it is not appended:

Expressions in the Expression Builder are complete when the expression’s type has been fulfilled. This makes building certain expressions impossible. Turn on the “experimental” parentheses feature in Settings > Version (down at bottom) and you’ll make Bubble more powerful and your life much easier.

There are no explicit looping constructs in Bubble. No explicit for, for… in, for… of, while, or do… while loop constructs like we have in JavaScript. There is implicit iteration going on all over the place, however. Note that list operators offer some help here, but Bubble is only half-baked as an array-oriented language.

Many things we might do with trivial loops in other environments can be accomplished simply and elegantly with list expressions (e.g., do two lists contain any of the same items? That’s list 1 :intersects with list 2 :count > 0), but the full complement of list expressions we might expect in a truly array-oriented language is missing.

There’s no generic .map() function, but there is one for lists of texts (arrays of strings) in the form of :each item formatted as....

There is a well-specified .filter() operator (:filter) with an “Advanced” option that iterates through the list based on some expression that can reference “this item” (so it’s not like there isn’t a model for how this would work in Bubble’s visual programming paradigm, it’s just that a mapping function is not provided and this is borderline insane and/or cruel).

Edit: :point_up_2: if anyone from @bubble is reading this, it would be trivial to add an “app type” dropdown to the dialog for :filtered and then a second input field (that gives access to the same props as the filter expression dialog) and then let the user write any expression that resolves to the selected app type. For example, if we are filtering a list of Things and want to map to some number, I could write this Thing's value + 1 and, instead of returning the filtered list of things, return the filter/mapped list of numbers instead of the filtered list of Things. And, et viola, you’ve just solved 99% of the front end looping cases and added a map/filter function. Nobody can tell me that this is more than an afternoon’s work. Also, I would stop calling your array-oriented language half-baked, so there’s that.

Backend workflows can be recursive, however. On the client-side (where iteration would be more helpful and faster) you can turn to things like my List Shifter or Floppy plugins for various solutions to iteration/looping/additional array-oriented actions (there are other plugin solutions as well).

The only type of read/writable object available to the Bubble programmer is a Thing (a custom data type). Things can only be created via interaction with the database (Create a New Thing) and can only be changed by interaction with the database (Make Changes to a Thing, Make Changes to a List of Things). API response objects and options (individual members of an “Option Set”) are also objects, but are immutable/read-only.

Things can be thought of essentially as JavaScript objects and it is best to think of your database as holding JavaScript objects and NOT as “tables”. (The Bubble database does not literally store JavaScript objects in the same way as IndexedDB [which literally does store data as JavaScript objects] but conceptually the Bubble db is exactly like IndexedDB.) The Bubble database is indexed and the primary index is the Thing’s unique ID.

Things are also “custom data types” and can be said to have a data type of that Thing.

Bubble as a “programming language” is strongly typed. All expressions have a type. All fields have a type. All values have a type and single values (scalars) are distinct from lists (arrays). Writing an expression that resolves to a type that the field does not expect throws a warning in the Issue Checker.

All of the primitive Bubble data types (yes/no, number, and text) are their JavaScript equivalents (boolean, number, and string).

The Bubble date datatype is a JavaScript date object. The numeric range and date range datatypes are seen in Bubble as scalar values but are two-element JavaScript arrays that represent the endpoints of the range.

For all intents and purposes, the Bubble state known as “empty” or “is empty” is the special JavaScript object null. The Bubble expression “something is not empty” (sometimes found as “isn’t empty”) is the same thing as !something in JS.

In the same way that arrays are never null in JavaScript (because they are objects), lists in Bubble are never empty. As in JavaScript, the correct way to assess whether a list has any items in Bubble is to check its :count (the count will be 0 if the list has no items), which is equivalent to the length property of JS arrays.

Edit: I had meant to comment on undefined… There is no such thing as undefined in Bubble. All properties/things-we-might-refer-to must be declared in some way before we could possibly access them in the expression builder. Mostly this happens automatically (any element in Bubble has a variety of predefined exposed states, for example an input has a value output, which we can access as that_input's value… that value might be empty aka null, but it is never undefined). If something that once existed in a project then goes away (e.g., you delete an entire Thing/custom data type or remove a plugin whose outputs you referred to somewhere), the Issue Checker will throw an issue for any expression that refers to that missing or deleted property showing is as [missing something] or [deleted something].

Negating a boolean: The boolean negation operator is not obvious in Bubble, but it is the expression some_yes_no is "no". This is equivalent to !some_javascript_boolean.

All Things are also data types and an expression that resolves to some Thing or list of Things is said to be of that data type.

That’s all I got at the moment, but perhaps more will chime in here.


Tip: utilize custom events rather than falling into “condition hell” :wink:


You went above-and-beyond with this contribution. Thank you.


Wow. Thank you so much for this amazing reply. I’m sure it will be of help for others new to Bubble too as they are searching the forum for some answers.

I had stated “I’m still relatively new to Bubble, but not entirely new to programming”, but I realize I should have added the steps I’ve taken so far to get myself up to speed.

First, of course I have consumed most of the Bubble videos and documentation. I still have a little bit to cover.

I purchased the Think It, Build It course and have completed working through that. It was excellent and super helpful. That’s where I’ve picked up some of the tips like using a hidden popup with a group to hold a Thing so it’s data is accessible.

I read The Ultimate Guide To Bubble Performance and that was helpful because it’s not immediately obvious what code executes on the server vs. the client.

I am currently reading The Ultimate Guide To Bubble Security and am about 1/3 through that.

I also purchased the Building With Bubble course library and will be diving into those soon.

I’m doing everything I can to get up to speed as quickly as possible. My post here was to look for tips and strategies that are not as obvious from reading documentation.

Thanks again for this amazing reply.



I think I know what you mean. Instead of adding conditions to an element in the third tab, you are suggesting to create a custom event that is more easily labeled, organized and discoverable. Is that correct?

I’ve already run into this a little bit. I have one element with eight conditions on it. I’m sure that could grow even greater but already it posed a problem.

How do you recommend organizing the custom events? In the condition tab, they are executed bottom up, so if a condition is met it does not test the conditions above it. Is that correct? How would you replicate this in a custom event? Or is it not necessary to if that’s not the behavior you want? In other words, would you break up the conditions in a custom event to multiple custom events, even if they are triggered by the same trigger?

Thanks. This is exactly the sort of thing I am looking for.

1 Like

Wow, that was great. :exploding_head:

I wish there was a article like this when I started with Bubble. 🫠

I suggest Bubble add this answer to the documentation in a new section called “bubble for programmers”.

Thanks @keith 🫡

1 Like

Glad that was helpful, @ken1! I made a couple of edits/enhancements just now that I had previously left out. Another great resource (if I do say so myself) is any of my own videos that I post from time to time. When I was starting Bubble, I just wanted to “see someone doing Bubble stuff” and regardless of what I’m showing (usually some feature of one of my plugins), it’s quite useful to see how someone goes about doing some particular thing and I’m always dropping in little “did you know you can do [x}?” sorts of things. It’s even useful to watch me mess up and see how I figure out what went wrong or how I adjust things to me like I had originally envisioned them (I occasionally do this intentionally, but usually all f-ups I make are completely unscripted).

What I normally do for complex workflows is break the parts into different “functions” which are custom events that by themselves do one thing and hopefully can be reused. Bubble doesn’t let you return values from custom events yet but it’s the best way to organize big events :slight_smile:

Glad I could help


This topic was automatically closed after 70 days. New replies are no longer allowed.