System hard limits
System hard limits
When creating plugins for Bubble, it's important to be mindful of Bubble's hard system limits. These constraints for plugin development mirror those present in general Bubble development. See the Hard Limits article for more detail.
Building elements is one of the main possibilities that Bubble Plugins offer. Using JavaScript, you can create a new user experience for the end user, while letting plugin users leverage the visual editor to add the element to their app's pages, display dynamic data, and more.
Building an element requires you to be familiar with how elements work in Bubble, the different types of fields that can be filled for them, etc. Note that building elements requires some JavaScript and web development knowledge. We recommend asking for help on the forum if you need guidance when building a new plugin.
Note: different parts of the plugin will have different character limits depending on where they show up in the UI. Be sure to preview your plugin before publishing to make sure everything looks as desired.
Adding elements to a plugin
A plugin can offer any number of elements. You add a new element by clicking on the 'Add a new element' button, and navigate among elements by clicking on the relevant element (or subsection) in the left panel.
Testing a plugin
Elements should be tested in the editor and in run-mode. Testing will happen in edit-mode to see how the Property Editor renders, and mostly in run-mode when you'll test your code. You test a plugin by adding an app to your plugin, then clicking on the test button. If the plugin isn't already installed in your test app, it will be added automatically. It's a good habit to keep the test app open — clicking 'Go to test app' will refresh the existing tab and fetch the latest version of your plugin.
Building the element
Defining general properties
The first thing you need to do when building an element is define the Edit Mode properties that control how the element behaves in the editor. In particular, you'll need to pick a name, a category, an icon, and an image placeholder (running the element code in the editor isn't possible, so you should have an image that represents your element).
Once this is done, you'll start picking the properties that apply to the element and define the fields the user will have to fill when using it in their app. First, you have the option to use Bubble standard properties for simple CSS options — background properties, dimensions, borders, etc. — that will be applied to the outer div. These properties are optional; it's possible to build an element without relying on them (except position and size: if you want the element to be resizable, you'll need to pick the 'Resizable' option).
Note: When loading fonts from a source other than Google Webfonts, the library Bubble uses will append the font_face property with the suffix :::custom rather than the font family name.
Defining fields
The next section is where you define fields. A field is a property the user will fill in the Property Editor. A field is defined by a name, a caption, and an editor type.
You have several choices for the editor type:
Static Text, Static Number: a simple input where users type something.
Checkbox: a checkbox that returns true/false in run-mode.
Color: shows a color picker; the value will be the RGBA code of the color stop.
Dropdown: useful if you want to offer users a set of options. Enter the different options separated by commas in the following input.
Static Image: enables the user to upload an image.
Dynamic value: shows users a control where they can define a dynamic expression using the Bubble Composer. You'll need to define which type of data the control expects (text, number, address, etc.). The data may also be a list if you check the relevant box.
App Type: a specific case where users need to define the type of data used by your element. For instance, for a map element, you'd want a field for 'Type of markers', and users would pick one of their types. Once you've defined such a field, you can define additional fields that prompt the user to pick a field within that type — for example, for a map, users would need to specify which field of the type contains the address. You can restrict the field types shown, such as limiting to addresses only.
A field can be optional (and won't be marked as missing in the Property Editor) and 'In style'. If that box is checked, when users define a style for your element in the Bubble Editor, the field will be included. Typically, colors and other styling options will be in styles, while data sources won't.
Defining states
States let you expose data from your elements to other elements and actions in the Application Editor. For instance, an input can have a value, a map can have a 'selected marker', etc. While your code is responsible for keeping the state up to date, you need to declare the different states you want to expose. For each state, you'll need to define the data type so that Bubble knows how to interpret the value in the Editor.
States defined in plugin elements run some initialization code which is evaluated with ALL dynamic properties for that element. If you have a conditional plugin-defined (non-Bubble) property that depends on that element's own value, it will create a circular dependency error. Until a (breaking) fix is released, this error can be avoided by initializing the plugin element state in the Element's init code instead, for example: instance.publishState(state_id, initial_value)
Events and actions
Events and Actions are the way your element can trigger a workflow and be modified by the user's workflows.
Events can be triggered by your element. In order for your elements to trigger a workflow — like a click, for instance — you'll need to declare the different events your element can trigger so that Bubble can populate the relevant list in the Workflow Tab. Your code will then be responsible for triggering the event.
Elements can also have actions applied to them — for instance, resetting a map to hide all markers. The actual action is defined in JavaScript, but you'll need to define the action names and the fields that apply to each one. Field definitions work the same way as element fields.
Code
Once the different pieces of information are defined, you can get into the code of your elements at the bottom of the editor. For each function, you'll see a code editor and contextual documentation showing the different objects you can access. In particular, the instance object represents the element, while the context object gives you access to utilities such as the current user and a function to upload files.
An element is defined by a few functions. The initialize function is called as soon as the element is visible on the page and runs only once per instance. The update function runs as soon as one of the element's properties changes — it can be run many times, so your code should track what changes to avoid unnecessary operations. Actions are represented by a run action. See the loading data article for details on data loading and asynchronous vs synchronous code.
When testing your functions, you can add a debugger point so that execution stops when you run it with the debugger on (and the web inspector open). This lets you step through your custom code click-by-click.
