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

# Event Handlers

> Configure how UI components respond to user interaction and lifecycle events — run node actions, start workflows, navigate, run local scripts, and more — from a single Event Handlers panel.

export const release_1 = "5.10"

export const release_0 = "5.10"

## Overview

An **event handler** connects a UI component to something that happens when the user interacts with it or when a screen loads. Each handler has a **trigger** (the event, such as a click) and one or more **actions** (what runs in response, such as a node action or a workflow).

Event handlers are configured per component, in the **Event Handlers** section of the component's configuration panel. A single trigger can run an ordered chain of actions.

<CardGroup cols={2}>
  <Card title="One unified panel" icon="layer-group">
    UI events, UI actions, and AI triggers are all configured as event handlers in one place
  </Card>

  <Card title="Triggers to actions" icon="bolt">
    React to On Click, On Change, On Load, and On Display with a chain of typed actions
  </Card>

  <Card title="Run local scripts" icon="code">
    Update local data on the client with a JavaScript expression — no backend roundtrip
  </Card>

  <Card title="Ordered chains" icon="list-ol">
    Sequence multiple actions per trigger, with ordering and compatibility rules enforced
  </Card>
</CardGroup>

***

## Triggers

A handler reacts to one of six trigger events. The triggers available on a component depend on the component type and the context (Process vs UI Flow).

| Trigger             | Fires when                                                                     | Typical components                                                                                                          |
| ------------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------- |
| **On Click**        | The user clicks the component                                                  | Button, File Upload, Bulk File Upload, Image, Text, Collection Prototype                                                    |
| **On Change**       | The component's value changes                                                  | Form fields (input, text area, select, multi-select, date picker, slider, radio, checkbox, segmented button, switch), Table |
| **On Load**         | A screen is rendered for the first time in a session                           | UI Flow: Page, Zone, Tab Bar, Modal · Process: Tab                                                                          |
| **On Display**      | A screen becomes visible (initial render, navigating back, or a modal closing) | UI Flow: Page, Zone, Tab Bar · Process: Tab                                                                                 |
| **On Scroll**       | The user scrolls within a previewed document                                   | File Preview                                                                                                                |
| **On Document End** | The user reaches the end of a previewed document                               | File Preview                                                                                                                |

<Info>
  **Available starting with FlowX.AI 5.9.1.** The **On Scroll** and **On Document End** triggers on the File Preview component are handled by the web and Android renderers. A common use is consent and disclosure: keep a **Submit** or **Accept** action hidden or disabled until an On Document End handler confirms the user reached the end of the document (the handler can be a simple local script that sets a flag).
</Info>

<Note>
  **On Load vs On Display** — On Load fires once per component per session and does not re-fire on back/forward or breadcrumb navigation. In UI Flows, an explicit **Navigate To** action resets this: the destination screen's On Load re-fires so it can re-initialize data. On Display fires every time the component becomes visible. In UI Flows, **Modal** supports On Load only.
</Note>

### Conditional triggers

<Badge color="blue" icon="cloud">SaaS · {release_0}</Badge>

<Info>
  **Available on SaaS with FlowX.AI {release_0}.** This feature is live on managed (SaaS) deployments now. Self-hosted deployments will receive it with the next LTS release family.
</Info>

An event handler can run **only when a condition is met**. Set a **trigger condition** on the handler — an expression evaluated against the current data — and the handler's actions run only when it resolves to true. This lets one component drive different behavior depending on runtime state, without duplicating handlers. Configured in the Designer and honored by the web and Android renderers.

***

## Action types

The **Action Type** of a handler determines what runs. The available types depend on the context, the component, and the trigger.

| Action type                    | What it does                                                                                                                                                |
| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Node Action**                | Runs a manual node action configured on the same user task node (Process context).                                                                          |
| **Start Process**              | Starts a process instance.                                                                                                                                  |
| **Start Workflow**             | Triggers an integration workflow. Fire-and-forget; does not pause the current flow.                                                                         |
| **Start Project**              | Starts a new instance in another project/application.                                                                                                       |
| **Navigate To**                | Navigates to another screen within a UI Flow.                                                                                                               |
| **External**                   | Opens an external URL, optionally in a new tab. Supports `${variable}` values from data.                                                                    |
| **Upload**                     | Initiates a file upload. Available on file-upload components.                                                                                               |
| **Dismiss**                    | Dismisses a subprocess or closes a modal.                                                                                                                   |
| **Run Local Script**           | Evaluates a client-side JavaScript expression and merges the result into local data — no backend roundtrip. (See [Run Local Script](#run-local-script).)    |
| **Save Local Variable**        | Saves the current collection row's item into local data under a key — no backend roundtrip. (See [Save Local Variable](#save-local-variable), SaaS · 5.10.) |
| **Conversation Reply Trigger** | In Chat-Driven UI Flows, sends a reply trigger to the conversational agent with parameter mapping.                                                          |

**Which action types appear** depends on context, component, and trigger:

* **On Load / On Display** triggers: UI Flow → **Start Workflow** only; Process → **Node Action** only.
* **UI Flow** (other triggers): Start Process, Start Workflow, External, Navigate To, Dismiss. File-upload components add **Upload**.
* **Process** (other triggers): Node Action, Dismiss, Start Project, External. File-upload components → **Upload** only.
* **Run Local Script** is available on interactive and form-field components.
* **Conversation Reply Trigger** is available in UI Flow context when a chat surface is in scope.

***

## Configuring an event handler

Event handlers are configured in the **Event Handlers** section of the selected component's configuration panel.

<Steps>
  <Step title="Select the component">
    In the UI Designer, select the component (button, form field, page, modal, and so on) that should respond to an event.
  </Step>

  <Step title="Add a handler for a trigger">
    In the **Event Handlers** section, click **+** and choose the trigger event (On Click, On Change, On Load, or On Display). Handlers are grouped under their trigger.
  </Step>

  <Step title="Choose the action type and configure it">
    Pick an **Action Type** and fill in its fields (see [Action types](#action-types)). For example, a **Node Action** needs a **Node Action Name**; **External** needs a **URL**; **Start Workflow** needs a **Workflow**.
  </Step>

  <Step title="Order the chain (optional)">
    When a trigger has more than one action, drag handlers to set their execution order. The editor flags ordering or compatibility violations.
  </Step>

  <Step title="Save">
    Save the handler. Each handler is stored as an ordered action on the component's template configuration.
  </Step>
</Steps>

### Common handler options

Depending on the action type, a handler can include:

* **Show loader** — display a loader until a server-side event updates the data or screen.
* **Open in new tab** — for External actions, open the URL in a new tab.
* **Dismiss on completion** — dismiss the modal as part of a user-triggered action.
* **Hide Subprocess Navigation** — disable navigation to subprocesses (requires Open in new tab).
* **Add form to submit** — link the action to forms whose fields are validated before it runs (see [Form validation](#form-validation)).
* **Add custom keys / Exclude keys / Add custom body** — shape the data sent with the action. These three options appear only on **Action** (Start/Submit), **Upload**, and **Start Project** handlers:
  * **Add custom keys** — an include-list: restricts the submitted payload to the listed data-model paths (dot-separated, e.g. `application.client.firstName`).
  * **Exclude keys** — a deny-list applied after the include step: drops the listed paths from the submitted payload.
  * **Add custom body** — a JSON object sent with the action; supports `${...}` placeholders resolved from process data at runtime. A custom body on its own is **not** included in the node output — to keep its data, also list those keys under **Add custom keys**.

***

## Action chains

A single trigger can run several actions in sequence. The Designer enforces three kinds of rules:

* **Per-type limits** — one action of each type per trigger, except **Run Local Script**, which allows up to **five**.
* **Compatibility** — some action types cannot coexist on the same trigger. For example, in a UI Flow, **Start Process** cannot be combined with Navigate To, Dismiss, External, or Conversation Reply Trigger. The rules differ between UI Flow and Process contexts; custom components are exempt.
* **Ordering** — handlers run as a sequential chain in the order shown. Some types cannot follow others; the editor blocks invalid orderings. If an action in the chain fails, the local data-store changes made earlier in the chain are **rolled back**.

***

## Run Local Script

The **Run Local Script** action evaluates a JavaScript expression on the client and merges the returned object into the local data store. There is no backend roundtrip, so the UI updates instantly. This is the same client-side mechanism that was previously called a "UI event."

<Warning>
  **Data availability** — a Run Local Script expression can only access data already sent from the backend to the frontend for display on the current screen. Referencing a property that isn't on the page will cause the expression to fail.
</Warning>

### Writing the expression

Use the same `${}` syntax as [computed values](./dynamic-and-computed-values#computed-values). Instead of returning a single value, return an object that updates the local data store:

```javascript theme={"dark"}
// Access data using ${} syntax
const calculatedValue = ${client.debt} / ${client.income};

// Return an object to update local data
return {
  "client": {
    "debtPercentage": calculatedValue
  }
}
```

| Aspect             | Business Rule            | Run Local Script  |
| ------------------ | ------------------------ | ----------------- |
| **Logic language** | Python, JavaScript, MVEL | JavaScript only   |
| **Output syntax**  | `output.put(key, value)` | `return { }`      |
| **Execution**      | Server-side              | Client-side (SDK) |
| **Latency**        | Network roundtrip        | Instant           |

Values updated by Run Local Script remain **local to the UI** until a submit action sends them to the process engine. On an On Click handler, the script evaluates before any other action on the same trigger — useful for setting a selected item's ID right before an action fires.

<Tabs>
  <Tab title="Calculate percentage">
    ```javascript theme={"dark"}
    const prc = ${client.debt} / ${client.income};
    return { "client": { "debtPrc": prc } }
    ```
  </Tab>

  <Tab title="Conditional value">
    ```javascript theme={"dark"}
    const amount = ${app.loanAmount};
    const status = amount > 100000 ? "high" : "standard";
    return { "app": { "riskCategory": status } }
    ```
  </Tab>

  <Tab title="Array totals">
    ```javascript theme={"dark"}
    const items = ${order.items} || [];
    const total = items.reduce((sum, item) => sum + item.price, 0);
    return { "order": { "totalAmount": total, "itemCount": items.length } }
    ```
  </Tab>
</Tabs>

<Tip>
  Keep Run Local Script expressions lightweight — they run synchronously on the UI thread. For heavy logic, use a server-side business rule. In Reusable UI Templates, any keys referenced in the expression must be mapped through the template's input parameters.
</Tip>

***

## Form validation

When a handler has one or more forms linked via **Add form to submit**, the platform validates all visible, enabled fields in those forms before the action runs. If any field fails, the action is blocked and errors are shown.

<Warning>
  **Hidden and disabled fields skip validation.** When a field is hidden by a hide condition, its validators are removed and any errors are cleared (they re-apply when it becomes visible). Disabled fields are also treated as valid. This prevents invisible fields from blocking progress — if you rely on validation for data integrity, give hidden fields valid defaults or validate them on the backend.
</Warning>

<Tip>
  If no forms are selected in **Add form to submit**, no client-side validation runs and the action executes immediately. Use this for "Save as Draft"-style actions that should allow incomplete data.
</Tip>

***

## Action specifics

### External

External actions open a URL, optionally in a new tab. URLs support `${variableName}` placeholders resolved from process data at runtime (a missing variable resolves to `null`):

* `https://example.com/users/${userId}`
* `${externalSystemUrl}/api/resource`

### Start Workflow

Select the **Workflow** to trigger and provide **Start params**. When triggered from a button inside a modal, **Dismiss modal** dismisses the modal as part of the action.

<Warning>
  Start Workflow is fire-and-forget — it does not pause the current process or wait for the workflow to finish.
</Warning>

### Dismiss

Dismiss calls the backend to dismiss the current process instance and sets the process and its active subprocesses to the terminal **DISMISSED** state. It requires only a name and optional analytics parameters — no form submission or custom keys.

<Note>
  A modal's own **Dismissible** property (close-on-backdrop-click and optional confirmation alert) is separate from the Dismiss action. For modal lifecycle guidance, see [Process design principles](../process/design-principles#modals-are-dismissed-only-by-user-interaction).
</Note>

### Save Local Variable

<Badge color="blue" icon="cloud">SaaS · {release_1}</Badge>

<Info>
  **Available on SaaS with FlowX.AI {release_1}.** This feature is live on managed (SaaS) deployments now. Self-hosted deployments will receive it with the next LTS release family.
</Info>

The **Save Local Variable** action saves the current collection row's item into the local data store under the key you set in **Row Item Save Key** — entirely client-side, with no backend roundtrip. Use it on a component inside a collection to capture the clicked row's data so other handlers or components on the same screen can reference it (for example, storing the selected row before a follow-up action fires).

<Note>
  Save Local Variable is not available inside Reusable UI Templates.
</Note>

***

## Migrating from UI events and UI actions

In 5.1.x, three separate surfaces existed: **UI events** (client-side expressions), **UI actions** (backend interactions), and **AI triggers** (conversation replies). In 5.9.0 they are unified into Event Handlers:

| 5.1.x                                                                     | 5.9.0                                               |
| ------------------------------------------------------------------------- | --------------------------------------------------- |
| UI event expression (`onChange` / `onClick` / `onLoad` / `onDisplay`)     | **Run Local Script** action on the matching trigger |
| UI action (Node Action, Start Process, External, Navigate To, Dismiss, …) | The corresponding **action type** on a handler      |
| AI trigger (conversation reply)                                           | **Conversation Reply Trigger** action               |

The trigger names map one-to-one (`onClick` → On Click, `onChange` → On Change, `onLoad` → On Load, `onDisplay` → On Display). Behavior is unchanged — Run Local Script still evaluates a client-side expression and merges the result into local data. The storage model changed: handlers are now backend-persisted, ordered action objects on the component's template configuration rather than inline `flowxProps.events` entries.

***

## Related resources

<CardGroup cols={2}>
  <Card title="Dynamic & computed values" icon="wand-magic-sparkles" href="./dynamic-and-computed-values">
    Expressions for hide conditions and computed values
  </Card>

  <Card title="Validators" icon="check" href="./validators">
    Configure validation rules for form fields
  </Card>

  <Card title="Buttons" icon="square" href="./ui-component-types/buttons">
    Configure button components that trigger event handlers
  </Card>

  <Card title="Adding an action to a node" icon="plus" href="../../flowx-designer/managing-a-project-flow/adding-an-action-to-a-node">
    Configure the node actions that Node Action handlers call
  </Card>
</CardGroup>


## Related topics

- [Image](/5.9/docs/building-blocks/ui-designer/ui-component-types/image.md)
- [FlowX.AI 5.9.0 Release Notes](/release-notes/v5.x/v5.9.0-june-2026/v5.9.0-june-2026.md)
- [Slider](/5.9/docs/building-blocks/ui-designer/ui-component-types/form-elements/slider.md)
- [Datepicker](/5.9/docs/building-blocks/ui-designer/ui-component-types/form-elements/datepicker-form-field.md)
- [Radio](/5.9/docs/building-blocks/ui-designer/ui-component-types/form-elements/radio-form-field.md)
