Template Syntax
Hologram templates use a custom syntax called "HOLO" that combines HTML with Elixir expressions.
Regular HTML Markup
You can use standard HTML elements and attributes in your templates:
<div class="container">
<h1>Hello World</h1>
<p>This is a paragraph.</p>
</div>
Accessing Props and State
Props and state are accessible in templates using the @var
syntax. This provides a convenient way to reference component data. For example, if you have a prop or state variable named count
, you can access it as @count
in your template.
In the following sections, you'll see how to use these variables in Elixir expressions for interpolation and control flow blocks.
Component Nodes
Components can be used as custom elements in your templates. They can receive props (properties) as attributes. String props can be given as regular double-quoted attributes, while other Elixir values (like numbers, booleans, or expressions) are given using curly braces syntax:
<MyComponent title="Hello" count={42} />
For more information about components and their props, see the Components documentation.
Elixir Expression Interpolation
You can embed Elixir expressions in your templates using curly braces:
Inside Text
<p>Hello, {@name}!</p>
Inside Attributes and Props
You can interpolate Elixir expressions in attributes and props in two ways.
First, you can interpolate the entire attribute value:
<div class={@class_name}>Content</div>
Or you can interpolate part of the attribute value within double quotes:
<div class="base-class {@dynamic_class}">Content</div>
Both approaches work for regular HTML attributes and component props:
<MyComponent count={Enum.count(@items)} label="Welcome, {@count}" />
Control Flow Blocks
If Block
Use {%if}
blocks for conditional rendering. The condition follows Elixir's truthiness rules - only nil
and false
are considered falsy, while any other value is considered truthy. You can optionally include an {%else}
branch.
Simple if block without else:
<div>
{%if @show_message?}
<p>Message is visible</p>
{/if}
</div>
If block with else branch:
<div>
{%if @show_message?}
<p>Message is visible</p>
{%else}
<p>Message is hidden</p>
{/if}
</div>
For Block
Use {%for}
blocks to iterate over collections. The syntax follows Elixir's comprehension rules, allowing you to use the same pattern matching and filtering capabilities as regular Elixir comprehensions.
<ul>
{%for item <- @items}
<li>{item.name}</li>
{/for}
</ul>
Event Binding
You can bind events to elements using event attributes. For detailed information about event binding syntax and available event types, see the Events documentation.
Escaping Curly Braces
To output literal curly braces in your template, escape them with a backslash:
<p>\{@literal\} {@variable}</p>
Raw Block
Use {%raw}
blocks to output content without processing:
<div>
{%raw}
This content will be output as-is, including any \{curly braces\} or \{%control\}...\{/flow\} syntax.
{/raw}
</div>
HTML Comments
You can use standard HTML comments in your templates:
<div>
<!-- This is a comment that will be visible in the HTML output -->
<p>Content</p>
</div>