Commands
Commands in Hologram are server-side operations that allow you to:
- Execute server-side logic
- Access server-only resources (like databases, files, or APIs)
- Manage server-side state (cookies and session)
- Perform privileged operations
- Trigger client-side actions (like updating UI state)
They are typically used for operations that require server processing, and are always executed asynchronously.
Defining Commands
Commands are defined as functions in your page or component modules using the following syntax:
def command(name, params, server) do
# Command logic here
end
For example:
def command(:save_user, params, server) do
case MyApp.Users.create(params) do
{:ok, user} ->
put_action(server, :user_saved, user: user)
{:error, changeset} ->
put_action(server, :validation_failed, errors: changeset.errors)
end
end
Command Parameters
Commands receive three arguments:
name
- the atom representing the command nameparams
- a map containing:- Custom parameters that can come from:
- Template event attributes
- Actions via
put_command/3
- Event data under the
:event
key (like%{page_x: 100, page_y: 200}
for mouse events)
- Custom parameters that can come from:
server
- the current%Server{}
struct
Command Results
Commands must return a %Server{}
struct. This struct not only manages server-side state (session and cookies) but also includes instructions for what happens next through functions that can be called on it. These functions are pure - they don't cause any side effects and simply return a new modified %Server{}
struct. Since these functions return the modified %Server{}
struct, they can be chained together using the pipe operator |>
, allowing for a clean and composable way to combine multiple state changes and behaviors.
Within a command, you can:
Trigger a Client Action
Action with the specified name without any additional parameters:
put_action(server, :my_action)
Action with the specified name and additional parameters provided as a keyword list:
put_action(server, :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(server, name: :my_action, target: "other_component", params: %{key: value})
Using an %Action{}
struct:
put_action(server, %Action{name: :my_action})
Update Session Data (coming soon)
Future versions of Hologram will support managing session data, for example using put_session/3
:
put_session(server, :user_id, user.id)
Update Cookies (coming soon)
Future versions of Hologram will support managing browser cookies, for example using put_cookie/3
:
put_cookie(server, :remember_token, token)
Navigate to Another Page (coming soon)
Future versions of Hologram will support server-side navigation, for example using put_page/3
:
put_page(server, ProductPage, id: product.id)
Triggering Commands
Commands can be triggered using event attributes in templates or from actions.
Template Event Attributes
Trigger a command named :my_command
, 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={command: :my_command, target: "other_component", params: %{a: 1, b: 2}}>Click me</button>
From Actions
Commands can also be triggered from actions using put_command/3
:
def action(:save_form, params, component) do
component
|> put_state(:saving, true)
|> put_command(:save_user, user: params.user)
end
Command Targets
By default, commands 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={command: :my_command, 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