1st recommendation, u can copy what i did on the landing page.
Editor :
https://bubble.io/page?id=testlpu&tab=Design&name=customuzed_field_builder&type=page&type_id=user&elements=bTKjMpreview mode:
https://testlpu.bubbleapps.io/version-test/customuzed_field_builder?debug_mode=true2 — Install & place the element
In Bubble editor → Plugins → Add the plugin package (Dynamic Custom Fields Builder) or upload it.
In your page, from Visual Elements choose Dynamic Fields Builder and drop it onto the page.
Select the element and set the property debug_mode = yes while you develop (turn off in production).
Leave other settings default unless you added theme options.
3 — Minimal UI you must create (Bubble native elements only)
We are deliberately not using the plugin to provide UI. Instead create a small control area so Bubble users can visually add/update fields:
A. Controls (above / anywhere on page)
Button "Add Field" → Workflow: Plugin Action add_field
Inputs for the action: label, type, is_list (if dropdown), required etc.
Example default call: add_field with properties:
label = Input A's value (or "Field X")
type = Dropdown (text/number/dropdown/checkbox/datepicker)
Field_Options = Input for options (comma separated) or empty
Button "Load Structure" → Workflow: Plugin Action load_structure
Input: text area that contains JSON from DB or sample
Button "Update All Fields" → Workflow: Plugin Action update_all_fields
This reads the DOM inputs using the field_data_<index> & field_datetime_<index> ids and writes JSON + publishes states
Button "Clear All" → Workflow: Plugin Action clear_all_fields
Button "Save Structure to DB" → Save DynamicCFB's json_structure to a thing’s form_json field (or run an API workflow)
B. Repeating Group (visual builder)
Data source: Dynamic Fields Builder's fields_names (so one cell per field)
Inside each cell place:
Text element: Current cell's index (for clarity)
Text: Current cell's field name (bind to DynamicCFB's fields_names:item #Current cell's index)
Type label: DynamicCFB's fields_types:item #Current cell's index
Input (Text) for editing text values: give it the ID field_data_ + Current cell's index (use the element property -> ID Attribute)
Example: set the element's ID attribute to field_data_1 using "i.e. id attribute = field_data_Current cell's index" — Bubble doesn't let dynamic id attribute in editor; instead in editor set the id to field_data_ and rely on actions to pick by index. If bubble requires literal: create the inputs programmatically — typical approach: create generic input without ID but set "ID attribute" to field_data_ + Current cell's index using "Attribute" mapping methods. If plugin code uses jQuery #field_data_1 etc you must set the static id values. Practical method: Use a custom HTML element or run a small workflow to set DOM id on page load. (See step 6 for exact, Bubble-friendly way.)
Date picker: give it ID attribute field_datetime_<index> (same notes)
Dropdown for field options: choices source = DynamicCFB's fields_options_grouped_clean:item #Current cell's index:split by , (or DynamicCFB's fields_options_grouped_clean:item #Current cell's index if plugin publishes it as a true list)
Delete button: Workflow calls plugin delete_field action with field_name = Current cell's field name
(Optional) Move up / move down: call actions to reorder JSON (if you implemented reorder)
IMPORTANT PRACTICAL NOTE about IDs in Bubble editor
Bubble editor does not let you set dynamic ID attributes per cell easily. Two practical approaches:
Use a plugin-free simple technique: place plain inputs without IDs and use workflows that call update_json_field with the value from Input A inside the cell — pass that value to the plugin action update_json_field(field_name = Current cell's fieldname, new_data_json = Input A's value). This avoids DOM id usage entirely.
If you must use update_all_fields action (which reads DOM elements by IDs), ensure your RG produces inputs with static IDs per index: create a repeating group of fixed number of cells or use client-side JS to add IDs on page load. I recommend using the value-passing per-cell approach — it’s Bubble-perfect.
4 — How to wire Actions (exact examples)
A. Add a field (via UI)
Workflow:
When Button Add Field is clicked → Action: Plugin → add_field
Params:
label = Input_Label's value (or "New Field")
type = Dropdown_Type's value ("Dropdown" / "Input" / "Datetime" / "Checkbox" / "Number")
options = Input_Options's value (comma-separated) — plugin will parse or accept arrays
required = checkbox value
After success: optionally run Display data or refresh RG
B. Load structure from DB (when page loads or via button)
Workflow:
Step 1: Get thing with form_json (DB) — action "Get data from page URL" or retrieve thing
Step 2: Plugin → load_structure
Param json_input = that thing's form_json
End: plugin will publish states (fields_names, fields_options_grouped_clean, fields_data_serialized, fields_datetime_serialized, etc.)
C. Update a single field (per-cell update)
When user edits Input inside a RG cell:
Workflow: Button Update Field (in cell) clicked → Plugin Action update_json_field
Params:
field_name = Current cell's field name (use DynamicCFB's fields_names:item #Current cell's index or Current cell's field_name)
new_data_json = Input_in_cell's value (or datePicker's value)
json_input = DynamicCFB's json_structure if you want plugin to use latest
debug_mode = yes/no
After success: plugin publishes states; available field_updated event triggers.
D. Update all fields (bulk single action)
When you want to read values in many inputs and write at once:
Workflow: Button "Update All" clicked → Plugin Action update_all_fields
The action expects the DOM or values to be available. If you used per-cell input workflows, you may not need this action. If you do use it, make sure your inputs have the IDs the plugin expects or you use the 1-by-1 update_json_field pattern.
E. Delete a field
Workflow: Button Delete in cell → Plugin Action delete_field
Param: field_name = Current cell's field name
F. Clear all fields
Workflow: Button Clear All → Plugin Action clear_all_fields
5 — Repeating group setup for dropdowns (user friendly, no advanced filters)
Recommended (easiest and most reliable):
RG data source: Dynamic Fields Builder's fields_names
Inside cell:
Dropdown element:
Type of choices: text
Choices source:
Dynamic Fields Builder's fields_options_grouped_clean:item # Current cell's index:split by ,
(Build by selecting fields_options_grouped_clean → :item # → Current cell's index → :split by and enter ,.)
Default value:
Dynamic Fields Builder's fields_data_serialized:item # Current cell's index
If fields_options_grouped_clean is empty for a cell, the dropdown choices will be empty — use conditional visibility to hide dropdown for non-dropdown types:
Dropdown visible only when Dynamic Fields Builder's fields_types:item #Current cell's index contains dropdown.
Alternative helper approach (if you prefer simpler editor steps):
Inside cell add a (hidden) Text element and set its text to:
Dynamic Fields Builder's fields_options_grouped_clean:item # Current cell's index
Set dropdown choices to:
This Text's value:split by ,
This is editor-friendly because connecting Dropdown to another element's value is simple to click.
6 — Save JSON to Bubble DB & load back (common flow)
A. Save structure after editing:
Use plugin state json_structure (string) or fields_* states to construct DB field.
Workflow: Button Save → Action "Make changes to a thing" → set form_json = Dynamic Fields Builder's json_structure
Done.
B. Load structure on page load:
Page load event → Step: Get thing FormRecord with form_json
Plugin action load_structure (or call parseAndPublish) with json_input = FormRecord's form_json
Plugin publishes all states and your RG fills.