> ## 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.

## 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 four 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                                                                                 |

<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>

***

## 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).) |
| **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.

***

## 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={"system"}
// 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={"system"}
    const prc = ${client.debt} / ${client.income};
    return { "client": { "debtPrc": prc } }
    ```
  </Tab>

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

  <Tab title="Array totals">
    ```javascript theme={"system"}
    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>

***

## 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>
