# ⚡ Actions
Actions are the bridge between HTML and JavaScript in Clera. An action is a JavaScript function that runs when an element is clicked or a form is submitted.
---
## 📝 Declaring an action
Add the `action` attribute to any element:
```html
✕
```
For forms, use `action` on the `
```
---
## ✍️ Writing the function
Write a plain JavaScript function with the same name:
```js
function openMenu() {
// runs when the button is clicked
}
function addTask(context) {
const title = context.values.title;
// runs when the form is submitted
}
```
That is all. No registration. No imports. Clera finds the function by name.
---
## ⚡ Action resolution order
When an action is triggered, Clera looks for the handler in this order:
1. **Page-local actions**: registered via `app.page("pageName", { actions: { ... } })`
2. **Global registered actions**: set via `app.actions = { ... }`
3. **Global functions**: plain `function myAction() {}` found via `window["myAction"]`
The first match wins. If nothing is found:
```
[CLERA:ACTION_NOT_FOUND] Action "addTask" not found on page "home".
```
---
## ⚠️ Exact name match
The HTML `action` attribute value must match the JavaScript function name exactly:
```html
```
---
## 🎯 context is optional
Clera always passes `context` as the first argument. Declaring it in the function signature is optional:
```js
// Both are valid:
function openMenu() {
console.log("Menu opened");
}
function openMenu(context) {
console.log("On page:", context.pageName);
}
```
JavaScript ignores extra arguments automatically.
---
## ⚡ Async actions
Actions can be async. Clera handles the returned Promise and logs any unhandled rejections to the diagnostics console:
```js
async function loadData(context) {
const response = await fetch("/api/data");
const data = await response.json();
context.render("#content", data.html);
}
```
---
## 🎯 Inline arguments
Arguments can be passed directly in the `action` attribute. Two syntaxes are supported and are fully equivalent:
**Colon syntax:** `action="fnName: arg1, arg2"`
```html
```
**Function-call syntax:** `action="fnName(arg1, arg2)"`
```html
```
The runtime converts function-call syntax into colon syntax before parsing. Both produce identical results. Use whichever reads more naturally in context.
---
### Reading args in the handler
Args land on `context.args` (frozen array) and `context.arg` (first item shorthand, `null` when no args):
```js
function deleteTask(context) {
const id = context.arg; // 42, first arg shorthand
}
function move(context) {
const id = context.args[0]; // resolved value of {task.id}
const status = context.args[1]; // "done"
}
function noArgs(context) {
context.arg; // null
context.args; // []
}
```
---
### Supported arg types
| Written in HTML | JS type | Value in handler |
|----------------|---------|-----------------|
| `42` / `3.14` | number | `42` / `3.14` |
| `'text'` or `"text"` | string | `"text"` |
| `true` / `false` | boolean | `true` / `false` |
| `null` | null | `null` |
| `{path}` | state binding | value at `path` in page or global data, resolved at click time |
String args must be wrapped in single or double quotes. An unquoted word that is not a known literal (`true`, `false`, `null`) or a number is passed through as a plain string:
```html
```
State bindings (`{path}`) resolve from page-local data first, then global data, at the moment the element is clicked. They are not re-evaluated on render cycles.
---
## 💡 Button inside a form
A `