How to use Bubble reusable element properties in dynamic JavaScript workflow
Bubble offers great flexibility for building web applications without code. One of its most powerful features is Reusable Elements, which allows you to build components once and use them across multiple pages. However, passing dynamic data into these reusable elements, especially when they need to behave differently based on the page context (such as a list page versus a detail page), can sometimes be a challenge.
This tutorial will guide you through creating a universal "Add to Compare" button as a reusable element. This button will dynamically add single tools (from a detail page) or multiple selected tools (from a repeating group on a list page) to a comparison list stored in localStorage
, all while maintaining a single, efficient JavaScript workflow within the reusable element.
This pattern is adaptable and can be used for any scenario where a reusable element needs to receive specific context or data from the page on which it resides.
Key concepts we’ll cover:
- Reusable element properties: Passing data into reusable elements.
- Custom states: Temporarily storing dynamic data on pages and within reusable elements.
- Repeating group checkboxes: Tracking selected items in a list.
- Bubble workflows: Orchestrating logic and data flow.
- JavaScript &
localStorage
: Client-side data storage for comparison features.
Problem
You have an "Add to Compare" button that uses JavaScript and localStorage
to manage a list of tools for comparison.
- On a detail page, this button should add one specific tool.
- On a list page with a repeating group, it should add multiple selected tools (via checkboxes).
- The challenge is to use a single reusable element for this button and ensure it receives the correct tool data regardless of the page it's on, without breaking its core JavaScript logic.
Solution
The core of the solution involves:
- A Reusable Element property: This property will receive the tool IDs from the parent page.
- Parent page workflows: These workflows will dynamically set the reusable element's property based on whether it's a detail page (one ID) or a list page (multiple IDs).
- Reusable Element's internal JavaScript: This JavaScript will always read from its property, making it context-agnostic.
Step-by-Step Tutorial
Part 1: Set up Reusable Element
-
Create the Reusable Element:
- In your Bubble editor, go to
Pages
>Reusable Elements
and clickAdd a new reusable element
. - Name it something like
Add to Compare Button RE
. - Design your button visually within this reusable element. It might be a simple
Button
element, or a group containing text/icons. For this tutorial, we'll assume the main interactive element is aButton
inside.
- In your Bubble editor, go to
-
Add a property to the Reusable Element:
-
While in the
Add to Compare Button RE
editor, select the top-level reusable element itself (not the button inside it). -
In the Inspector panel (right sidebar), scroll down to "Property" and click "Add a new property".
-
Name:
toolIDsToCompare
-
Type:
Text
-
Is a list: Check this box. This is crucial if it needs to handle multiple IDs from the list page.
-
-
Implement the JavaScript workflow inside the Reusable Element:
- Select the Button element within your
Add to Compare Button RE
. - Right-click and select
Start/Edit workflow
. - Add an action:
Plugins
>Run Javascript
(You'll need the free "Toolbox" plugin installed for this). - Paste the following JavaScript code into the "Javascript code" field:
// Get the tool IDs from the reusable element's property // 'This Reusable Element' refers to the top-level reusable element // The value of 'toolIDToCompare' is passed into the JS context by Bubble. let toolIDToAddToCompare = '{{This Reusable Element's toolIDToCompare}}'; // Split the comma-separated string into an array. // Handle cases where the property might be empty or null (e.g., first load) let newIDsArray = toolIDToAddToCompare ? toolIDToAddToCompare.split(',') : []; // Get current items from local storage const currentLocal = localStorage.getItem('items_to_compare'); let existingLocalIDs = currentLocal ? currentLocal.split(',') : []; // Combine all IDs (new selections and existing local storage items) let combinedIDs = [...existingLocalIDs, ...newIDsArray]; // Remove any duplicates or tools with empty IDs (from splitting an empty string) combinedIDs = combinedIDs.filter((tool, index) => tool && combinedIDs.indexOf(tool) === index); // Get the final cleaned list as a comma-separated string const finalCompareList = combinedIDs.join(','); // Save to local storage if max 3 items if (combinedIDs.length <= 3) { localStorage.setItem('items_to_compare', finalCompareList); } else { // Optional: Handle the case where more than 3 items are selected. // We'll store only the first 3 to respect the limit. localStorage.setItem('items_to_compare', combinedIDs.slice(0, 3).join(',')); console.warn("More than 3 items selected for comparison. Only the first 3 will be stored."); } // Send the final list back to Bubble using a Javascript to Bubble element. // Ensure you have a 'Javascript to Bubble' element on *each page* that uses this RE, // and its ID matches 'jsToBubble_CompareList'. bubble_fn_jsToBubble_CompareList(finalCompareList);
- Select the Button element within your
Part 2: Set up a list page (with Repeating Group)
-
Create a Page-Level Custom State for Selections:
-
Go to your "List Page" (where your repeating group of tools is displayed).
-
Select the page itself (or a relevant parent group on the page).
-
In the Inspector panel, add a new custom state:
- Name:
selectedTools
- Type:
Text
- Is a list: Check this box.
- Name:
-
-
Configure Repeating Group Checkboxes:
-
Inside your repeating group's cell, add a
Checkbox
element. -
Create two workflows for this checkbox:
-
Workflow 1: When Checkbox is Checked
-
Action:
Set state of an element
-
Element: Your
Page
(or group whereselectedTools
is defined). -
Custom state:
selectedTools
-
Value:
Your Page's selectedTools:plus item Current cell's Parent Group Tool's ID
- (Replace
Parent Group Tool's ID
with the actual field from your data type that stores the tool's unique identifier/ID).
- (Replace
-
-
Workflow 2: When Checkbox is Unchecked
- Action:
Set state of an element
- Element: Your
Page
. - Custom state:
selectedTools
- Value:
Your Page's selectedTools:minus item Current cell's Parent Group Tool's ID
- Action:
-
-
-
Place the Reusable Element on the list page:
- Drag and drop your
Add to Compare Button RE
onto your list page.
- Drag and drop your
-
Pass data to the Reusable Element's property:
-
Select the instance of your
Add to Compare Button RE
on the list page. -
In the Inspector panel, you will see a property field for
toolIDsToCompare
. -
Set this property's value to:
Your Page's selectedTools:formatted as text
-
When the "formatted as text" popup appears:
- Delimiter:
,
(comma) - This converts your list of selected IDs into a single comma-separated string, ready for your JavaScript.
- Delimiter:
-
-
-
Add a
Javascript to Bubble
element:- Place a
Javascript to Bubble
element (from the Toolbox plugin) anywhere on your list page. It can be hidden. - Element ID:
jsToBubble_CompareList
(ensure this exactly matches thebubble_fn_jsToBubble_CompareList
call in your JavaScript). - Event name: (Optional, but good practice if you want to trigger specific workflows).
- Value type:
text
.
- Place a
Part 3: Set up detail page (Single tool)
-
Place the Reusable Element on the detail page:
- Drag and drop your
Add to Compare Button RE
onto your detail page. Ensure your detail page or a parent group on it has its "Type of content" set to "Tool" and is displaying a single tool's data.
- Drag and drop your
-
Pass data to the Reusable Element's property:
- Select the instance of your
Add to Compare Button RE
on the detail page. - Locate the
toolIDsToCompare
property. - Set this property's value to:
Current Page's Tool's ID
(orParent group's Tool's ID
, depending on where your single tool's data is exposed).
- Select the instance of your
-
Add a
Javascript to Bubble
element:- Place a
Javascript to Bubble
element (from the Toolbox plugin) anywhere on your detail page. - Element ID:
jsToBubble_CompareList
(again, matching the JavaScript call). - Value type:
text
.
- Place a
Conclusion
By leveraging reusable element properties to pass dynamic data from the parent page, you can create a single, efficient element that intelligently handles both single and multiple selections. This approach maintains clean workflows, reduces redundancy, and makes your Bubble application more scalable and maintainable.
This pattern is adaptable and can be used for any scenario where a reusable element needs to receive specific context or data from the page on which it resides.
ABOUT ME
I'm Juliet Edjere, a no-code professional focused on automation, product development, and building scalable solutions with no coding knowledge.
I document all things MVP validation and how designs, data, and market trends connect.
Click. Build. Launch.
Visit my website → built with Carrd and designed in Figma