---
title: Call Handler
sidebarTitle: "Call Handler"
description: Invoke a developer-registered JavaScript handler from a UI interaction.
icon: bolt
---

`CallHandler` invokes a client-side JavaScript function registered by the app developer. Where `CallTool` crosses the network to your server, `CallHandler` runs instantly in the browser — ideal for state transformations like constraint enforcement, computed fields, or domain-specific logic that doesn't need server involvement.

```python
from prefab_ui.components import Slider
from prefab_ui.actions import CallHandler

Slider(name="infra", on_change=CallHandler("constrainBudget"))
```

Handlers are registered via `js_actions` on `PrefabApp`. See [Custom Handlers](/concepts/custom-handlers) for how to write and register them.

## Passing Arguments

Use `arguments` to pass extra data to the handler. Values support `{{ }}` interpolation, so you can pass client state at call time:

```python
from prefab_ui.components import Button
from prefab_ui.actions import CallHandler

Button("Recalculate", on_click=CallHandler(
    "recalculate",
    arguments={"mode": "aggressive", "total": "{{ budget }}"},
))
```

The handler receives these via `ctx.arguments`:

```javascript
// In js_actions
"recalculate": (ctx) => {
    const mode = ctx.arguments.mode;  // "aggressive"
    const total = ctx.arguments.total;  // resolved budget value
    // ... compute and return state updates
}
```

## Handling Results

The handler's return value is available as `$result` in `on_success` callbacks, just like `CallTool`:

```python
from prefab_ui.actions import CallHandler, SetState, ShowToast
from prefab_ui.rx import RESULT

Button("Validate", on_click=CallHandler(
    "validate",
    on_success=ShowToast("Valid!", variant="success"),
    on_error=ShowToast("Validation failed", variant="error"),
))
```

If the handler throws an exception, `on_error` fires with the error message in `$error`.

## Combined with Other Actions

Chain `CallHandler` with other actions in a list:

```python
from prefab_ui.actions import CallHandler, SetState

Slider(name="infra", on_change=[
    SetState("dirty", True),
    CallHandler("constrainBudget"),
])
```

## API Reference

<Card icon="code" title="CallHandler Parameters">
<ParamField body="handler" type="str" required>
  Name of the registered handler function. Can be passed as a positional argument.
</ParamField>

<ParamField body="arguments" type="dict[str, Any] | None" default="None">
  Extra arguments passed to the handler via `ctx.arguments`. Values support `{{ key }}` interpolation.
</ParamField>
</Card>

## Protocol Reference

```json CallHandler
{
  "action": "callHandler",
  "handler": "string (required)",
  "arguments?": "object"
}
```

For the complete protocol schema, see [CallHandler](/protocol/call-handler).
