Starlet9334
Reactivity in hologram or, why do my buttons don't do anything
Hello there,
I am trying to understand reactivity in hologram.
I’ve create a simple component calculator.ex that I am calling like this <Calculator cid="calculator" value="20" />
This is my component definition:
defmodule Calculator do
use Hologram.Component
prop :value, :integer
def template do
~HOLO"""
<button class="btn" $click="plus">Plus</button>
<button class="btn" $click="minus">Minus</button>
<p>The value is {@value}</p>
"""
end
def init(props, component) do
put_state(component, :value, props.value)
end
def action(:plus, _params, component) do
put_state(component, :value, component.state.value + 1)
end
def action(:minus, _params, component) do
put_state(component, :value, component.state.value - 1)
end
end
However, the displayed value doesn’t change when I hit any of the buttons.
What am I doing wrong?
Marked As Solved
bartblast
Thank you!
There a few problems in the code:
1)
You’ve got duplicate :only option in the Plug.Static config:
plug Plug.Static,
at: "/",
from: :hologram_tutorial,
gzip: not code_reloading?,
only: HologramTutorialWeb.static_paths(),
only: ["hologram" | HologramTutorialWeb.static_paths()]
should be:
only: ["hologram" | HologramTutorialWeb.static_paths()]
2)
You can’t use Phoenix routing-related stuff (like ~p sigil) in Hologram templates.
instead:
<link phx-track-static rel="stylesheet" href={~p"/assets/css/app.css"} />
use:
<link rel="stylesheet" href={asset_path("assets/css/app.css")} />
3)
Don’t use Phoenix CSRF tokens inside Hologram layouts.
remove:
<meta name="csrf-token" content={get_csrf_token()} />
CSRF protection is managed automatically by Hologram, you don’t have to think about it at all.
4)
You’re layout is broken, you need to use html as the root element, and nest header and footer elements inside the body element.
instead:
<head>
<title>{@page_title}</title>
<Hologram.UI.Runtime />
<link rel="stylesheet" href={asset_path("assets/css/app.css")} />
</head>
<header>Header with menu</header>
<body>
<slot />
</body>
<footer>Footer</footer>
use:
<!DOCTYPE html>
<html>
<head>
<title>{@page_title}</title>
<Hologram.UI.Runtime />
<link rel="stylesheet" href={asset_path("assets/css/app.css")} />
</head>
<body>
<header>Header with menu</header>
<slot />
<footer>Footer</footer>
</body>
</html>
5)
When initializing Hologram components server-side (e.g. when using the given component in a page template - since pages are always loaded from the server) you need to use init/3 instead of init/2.
For #5 the DX could be better and Hologram could allow to use init/2 in cases where there is no init/3 defined - added that to the backlog.
Also Liked
bartblast
Since fixing #5 alone solved everything, the repo you shared was probably different from your original code. No worries! Just want to make sure it’s clear - for you and anyone else reading this with similar issues: each of those 5 issues will cause Hologram to break in different ways, so if any are in your actual codebase, they’ll need addressing.
bartblast
Thanks, I’ll look at it!
Btw, this:
def init(props, component, server) do
component = put_state(component, :value, props.value)
{component, server}
end
Can be just this:
def init(props, component, _server) do
put_state(component, :value, props.value)
end
you don’t have to return server struct if it’s not modified ![]()
bartblast
I noticed that you initialized the value as a string, but you’re treating it as an integer using the plus/minus operators.
The runtime prop type validation isn’t working yet, which might be misleading you into thinking the value gets automatically converted to an integer. Is that what’s happening?
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #hex









