DEV Community

Explorer
Explorer

Posted on

Dynamic Multi-Select Dropdown Options via BeanShell Options Binder in Joget

In Joget DX forms, standard cascading drop-down lists work well when selecting a single parent item. However, when a user selects multiple items in a multi-select box or checkbox group, cascading target options requires a custom BeanShell Form Options Binder.

In this guide, we'll write a Java/BeanShell script that receives an array of selected parent keys, queries related child items from the database using SQL PreparedStatements, and returns a populated FormRowSet formatted for Joget Select Box and Multi-Select elements.


How It Works

  1. Array Inspection: When a parent multi-select field changes, the options binder receives an array of selected keys (values).
  2. Prepared Statement Loop: The script iterates through the selected parent IDs, executing a parameterized query to fetch corresponding child options.
  3. FormRowSet Construction: For each database match, a FormRow object is created with two essential properties:
    • FormUtil.PROPERTY_VALUE: The stored value / primary key.
    • FormUtil.PROPERTY_LABEL: The display label shown in the UI.

The BeanShell Form Options Binder Script

Open your Joget Form in Form Builder, select the target Multi-Select or Select Box element, set Options Binder to BeanShell Form Options Binder, and paste the script below:

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import javax.sql.DataSource;
import org.joget.apps.app.service.AppUtil;
import org.joget.apps.form.model.FormRow;
import org.joget.apps.form.model.FormRowSet;
import org.joget.apps.form.service.FormUtil;
import org.joget.commons.util.LogUtil;

FormRowSet optionRows = new FormRowSet();

// Ensure parent selection contains values
if (values != null && values.length > 0) {
    Connection con = null;
    PreparedStatement ps = null;
    ResultSet rs = null;

    try {
        DataSource ds = (DataSource) AppUtil.getApplicationContext().getBean("setupDataSource");
        con = ds.getConnection();

        if (con != null && !con.isClosed()) {
            // Build SQL query for matching child records based on selected parent categories
            String sql = "SELECT id, c_supplier_name, c_registration_code " +
                         "FROM app_fd_registered_suppliers " +
                         "WHERE c_category_id = ? " +
                         "ORDER BY c_supplier_name ASC";

            ps = con.prepareStatement(sql);

            for (Object valObj : values) {
                if (valObj == null) continue;
                String selectedCategoryId = valObj.toString().trim();
                if (selectedCategoryId.isEmpty()) continue;

                ps.setString(1, selectedCategoryId);
                rs = ps.executeQuery();

                while (rs.next()) {
                    String supplierId = rs.getString("id");
                    String supplierName = rs.getString("c_supplier_name");
                    String code = rs.getString("c_registration_code");

                    FormRow row = new FormRow();
                    row.setProperty(FormUtil.PROPERTY_VALUE, supplierId);
                    row.setProperty(FormUtil.PROPERTY_LABEL, supplierName + " (" + code + ")");

                    optionRows.add(row);
                }
                rs.close();
            }
        }
    } catch (Exception e) {
        LogUtil.error("MultiSelect Options Binder", e, "Error fetching dynamic options");
    } finally {
        if (rs != null) try { rs.close(); } catch (Exception e) {}
        if (ps != null) try { ps.close(); } catch (Exception e) {}
        if (con != null) try { con.close(); } catch (Exception e) {}
    }
}

return optionRows;
Enter fullscreen mode Exit fullscreen mode

AJAX Trigger Setup in Form Builder

To update the target multi-select dropdown immediately when the parent field selection changes without reloading the page:

  1. Edit the Target Multi-Select / Select Box in Form Builder.
  2. Under Advanced Options, check AJAX Change Option.
  3. Set Listen to Field to your parent Multi-Select element ID (e.g. category_ids).

Key Advantages

  • Multi-Parent Filtering: Unlike standard single-select cascading dropdowns, this script handles multi-selection filtering effortlessly.
  • SQL Injection Safe: Uses PreparedStatement.setString() to execute queries safely.

Top comments (0)