> ## Documentation Index
> Fetch the complete documentation index at: https://developer.kodexa.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Selection Option Formulas

> Compute dropdown options for SELECTION data elements dynamically using JavaScript formulas that evaluate per data object and react to attribute changes.

## Overview

Selection option formulas let you compute dropdown options dynamically at runtime instead of defining a static list. When a user opens a document, the formula evaluates for each data object and populates the dropdown with context-aware options. When referenced attributes change, the formula re-evaluates automatically and the dropdown updates in real time.

**Common use cases:**

* Load options from an external reference system via service bridges
* Filter options based on sibling attribute values (e.g., show subcategories for the selected category)
* Compute options based on document context

***

## Configuration

Two properties on a SELECTION data element enable formula-driven options:

```yaml theme={null}
- name: department
  label: Department
  taxonType: SELECTION
  useSelectionOptionFormula: true
  selectionOptionFormula: |
    serviceBridgeCall("myorg/reference-data", "list-departments", {
      region: getAttribute("region")
    })
```

### Properties

<ParamField path="useSelectionOptionFormula" type="boolean" default="false">
  When `true`, the formula is used instead of the static `selectionOptions` list to populate the dropdown.
</ParamField>

<ParamField path="selectionOptionFormula" type="string">
  JavaScript expression evaluated by the formula runtime. Must return an array of options (see [Return Format](#return-format) below).
</ParamField>

<Note>
  You can define both static `selectionOptions` and a `selectionOptionFormula` on the same data element. The formula takes precedence when `useSelectionOptionFormula` is `true`. This is useful for having a fallback list during development.
</Note>

***

## Return Format

The formula must return an array. Two formats are accepted:

**Object format (recommended):**

```javascript theme={null}
[
  { label: "Engineering", value: "ENG" },
  { label: "Marketing", value: "MKT" },
  { label: "Human Resources", value: "HR" }
]
```

**String format (simple):**

```javascript theme={null}
["Engineering", "Marketing", "Human Resources"]
```

When using string format, both label and value are set to the string.

Returning `null` or an empty array `[]` clears the dropdown options. The distinction is preserved: `null` means "no data available" while `[]` means "explicitly empty list."

***

## How It Works

```mermaid theme={null}
flowchart TD
    A[Document Opens] --> B[RecalculationService initializes]
    B --> C[Build selection formula dependency graph]
    C --> D[Evaluate formulas for all data objects]
    D --> E[Store results on DataObject.selectionOptions]
    E --> F[UI seeds dropdown cache from WASM]

    G[User edits attribute] --> H[Detect dependency change]
    H --> I[Re-evaluate affected formulas]
    I --> J[Compare with previous options via canonical JSON]
    J -->|Changed| K[Persist to database]
    K --> L[Emit selectionOptions:computed event]
    L --> M[UI updates dropdown in real time]
    J -->|Unchanged| N[Skip — no update needed]
```

Key points:

* Options are computed and **persisted on the DataObject** (not the attribute) -- they survive page reloads
* Change detection uses canonical JSON comparison (sorted keys) to avoid unnecessary updates
* During initial load, events are suppressed to prevent a flood -- the UI reads options from the WASM layer directly
* After initial load, real-time changes emit `selectionOptions:computed` events that update the UI reactively

***

## Referencing Sibling Attributes

Formulas can read the current data object's attribute values to parameterize API calls:

```javascript theme={null}
serviceBridgeCall("myorg/reference-data", "get-subcategories", {
  category: getAttribute("category"),
  region: getAttribute("region"),
  active: true
})
```

When any referenced attribute changes, the formula automatically re-evaluates.

***

## Service Bridge Integration

Most selection option formulas call a service bridge to fetch options from an external system:

```yaml theme={null}
- name: subcategory
  label: Subcategory
  taxonType: SELECTION
  useSelectionOptionFormula: true
  selectionOptionFormula: |
    serviceBridgeCall("myorg/reference-data", "get-subcategories", {
      category: getAttribute("category"),
      active: true
    })
```

The `serviceBridgeCall()` function is a convenience wrapper available in formula contexts. For the full service bridge API, see [Calling Service Bridges from Scripts](/guides/scripting/service-bridges).

***

## Grid Child Formulas

When a SELECTION data element is a child of a group (grid row), the formula evaluates per data object instance. Each row can have different dropdown options based on its own attribute values:

```yaml theme={null}
- name: line_items
  label: Line Items
  group: true
  children:
    - name: country
      label: Country
      taxonType: STRING

    - name: region
      label: Region
      taxonType: SELECTION
      useSelectionOptionFormula: true
      selectionOptionFormula: |
        serviceBridgeCall("myorg/geo-data", "regions-by-country", {
          country: getAttribute("country")
        })
```

In this example, each line item row gets its own region dropdown based on its own country value.

***

## Examples

<AccordionGroup>
  <Accordion title="Simple lookup" icon="list">
    Fetch a static reference list from an external system on document open.

    ```yaml theme={null}
    - name: currency
      label: Currency
      taxonType: SELECTION
      useSelectionOptionFormula: true
      selectionOptionFormula: |
        serviceBridgeCall("myorg/reference-data", "get-currencies", {})
    ```
  </Accordion>

  <Accordion title="Dependent dropdown" icon="link">
    Filter team members based on a selected department. When the user changes the department, the contact dropdown updates automatically.

    ```yaml theme={null}
    - name: team_lead
      label: Team Lead
      taxonType: SELECTION
      useSelectionOptionFormula: true
      selectionOptionFormula: |
        serviceBridgeCall("myorg/directory", "get-team-members", {
          departmentId: getAttribute("department_id")
        })
    ```
  </Accordion>

  <Accordion title="Multi-dependency with fallback" icon="code-branch">
    Use multiple attributes as dependencies and provide a fallback when the external call returns nothing.

    ```yaml theme={null}
    - name: priority_level
      label: Priority Level
      taxonType: SELECTION
      useSelectionOptionFormula: true
      selectionOptionFormula: |
        var amount = getAttribute("total_amount");
        var region = getAttribute("region");
        if (!amount || !region) return [];
        return serviceBridgeCall("myorg/rules-engine", "get-priority-levels", {
          amount: amount,
          region: region
        }) || [{ label: "Standard", value: "STD" }];
    ```
  </Accordion>
</AccordionGroup>

***

## Troubleshooting

<Warning>
  **Empty dropdown**

  Check that the service bridge is configured and the endpoint returns data. Use `log.debug(...)` in script steps to test the bridge response.
</Warning>

<Warning>
  **Options don't update**

  Verify that `useSelectionOptionFormula` is `true`. Check that the attribute names in `getAttribute()` match the data element names exactly.
</Warning>

<Warning>
  **Timeout errors**

  Selection option formulas have a 2-second timeout. If your external API is slow, consider caching results in the service bridge configuration.
</Warning>

<Warning>
  **Stale options after page reload**

  Options are persisted on the DataObject. If the external system's data changed, trigger a recalculation by editing one of the dependent attributes.
</Warning>
