Actions

Actions in Hologram are client-side operations that allow you to:

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:

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: