Actions
Actions in Hologram are client-side operations that allow you to:
- Update component state
- Trigger commands and other actions
- Navigate to another page
- Update emitted context
They are typically executed in response to user interactions, enabling dynamic and interactive web applications.
Defining Actions
Actions are defined as functions in your page or component modules using the following syntax:
def action(name, params, component) do
# Action logic here
end
For example:
def action(:update_count, params, component) do
put_state(component, :count, params.new_count)
end
Action Parameters
Actions receive three arguments:
name
- the atom representing the action nameparams
- a map containing:- Custom parameters that can come from:
- Template event attributes
- Other actions via
put_action/3
- Commands via
put_action/3
- Event data under the
:event
key (like%{page_x: 100, page_y: 200}
for mouse events)
- Custom parameters that can come from:
component
- the current%Component{}
struct
Action Results
Within an action, you can:
Update Component State
By setting the value for a single key:
put_state(component, :key, value)
With multiple key-value pairs using a keyword list:
put_state(component, key_1: value_1, key_2: value_2)
With multiple key-value pairs using a map:
put_state(component, %{key_1: value_1, key_2: value_2})
Update a nested value by specifying a path of keys:
put_state(component, [:path_key_1, :path_key_2], value)
Chain Another Action
Action with the specified name without any additional parameters:
put_action(component, :my_action)
Action with the specified name and additional parameters provided as a keyword list:
put_action(component, :my_action, param_1: value_1, param_2: value_2)
Action with a specified name, target, and parameters using a map for the parameters (in this longhand version, both params
and target
are optional):
put_action(component, name: :my_action, target: "other_component", params: %{param: value})
Using an %Action{}
struct:
put_action(component, %Action{name: :my_action})
Trigger a Command
Command with the specified name without any parameters:
put_command(component, :my_command)
Command with the specified name and additional parameters provided as a keyword list:
put_command(component, :my_command, param_1: value_1, param_2: value_2)
Command with a specified name, target, and parameters using a map for the parameters (in this longhand version, both params
and target
are optional):
put_command(component, name: :my_command, target: "other_component", params: %{param: value})
Command using a %Command{}
struct:
put_command(component, %Command{name: :my_command})
See also: Commands.
Navigate to Another Page
Page without params:
put_page(component, ProductsPage)
Page with params:
put_page(component, ProductPage, product_id: 123)
Update Emitted Context
By setting a value for a single key:
put_context(component, :key, value)
Using a tuple for namespacing, allowing different components to use the same key without conflict:
put_context(component, {MyModule, :key}, value)
See also: Context.
Actions must return a %Component{}
struct. This struct not only reflects changes to the component's state but also includes instructions for what happens next. These instructions can be in the form of a chained action, an enqueued command, a next page to navigate to, or an emitted context.
Triggering Actions
Actions can be triggered using event attributes in templates. There are several syntax options:
Text Syntax
<button $click="my_action">Click me</button>
Expression Shorthand Syntax
Without params:
<button $click={:my_action}>Click me</button>
With params:
<button $click={:my_action, a: 1, b: 2}>Click me</button>
Expression Longhand Syntax
Trigger an action named :my_action
, targeting component with CID "other_component"
and passing parameters a
and b
with values 1
and 2
, respectively (both target
and params
are optional):
<button $click={action: :my_action, target: "other_component", params: %{a: 1, b: 2}>Click me</button>
Action Targets
By default, actions are executed on the component that contains them. If the component is stateless (doesn't have a CID specified), the closest stateful component higher in the hierarchy is used. You can specify a different component for execution using the target
parameter:
<button $click={action: :my_action, target: "other_component"}>Click me</button>
Valid targets include:
"page"
- targets the current page"layout"
- targets the current layout component- a string representing a component ID (CID) - targets a specific component by its unique identifier within the application