I just started following the phoenix LiveView tutorial. The tutorial was a bit old so going through the changelog and discovered a few things which has changed since the last release. So I’m creating a socket here which has changed somehow.
def mount(_session, socket) do
{:ok, assign(socket, key: "max")}
end
def render(assigns) do
~L"""
<h1>Hi!</h1>
<%= assigns.key %>
"""
end
So how do I call the key to render function I tried @key also which didn’t work and using assigns.key is getting me this error
** (exit) an exception was raised:
** (KeyError) key :key not found in: %{flash: %{}, live_action: nil, live_module: ReactorWeb.FooLive, socket: #Phoenix.LiveView.Socket<assigns: %Phoenix.LiveView.Socket.AssignsNotInSocket{}, changed: %{}, endpoint: ReactorWeb.Endpoint, id: "phx-FhNxUCgprLDZCwKj", parent_pid: nil, root_pid: nil, router: ReactorWeb.Router, view: ReactorWeb.FooLive, ...>}
(reactor 0.1.0) lib/reactor_web/live/foo_live.ex:11: anonymous fn/2 in ReactorWeb.FooLive.render/1
(phoenix_live_view 0.13.0) lib/phoenix_live_view/diff.ex:221: Phoenix.LiveView.Diff.traverse/5
(phoenix_live_view 0.13.0) lib/phoenix_live_view/diff.ex:92: Phoenix.LiveView.Diff.render/3
(phoenix_live_view 0.13.0) lib/phoenix_live_view/static.ex:284: Phoenix.LiveView.Static.to_rendered_content_tag/4
(phoenix_live_view 0.13.0) lib/phoenix_live_view/static.ex:144: Phoenix.LiveView.Static.render/3
(phoenix_live_view 0.13.0) lib/phoenix_live_view/controller.ex:35: Phoenix.LiveView.Controller.live_render/3
(phoenix 1.5.3) lib/phoenix/router.ex:352: Phoenix.Router.__call__/2
(reactor 0.1.0) lib/reactor_web/endpoint.ex:1: ReactorWeb.Endpoint.plug_builder_call/2
(reactor 0.1.0) lib/plug/debugger.ex:132: ReactorWeb.Endpoint."call (overridable 3)"/2
(reactor 0.1.0) lib/reactor_web/endpoint.ex:1: ReactorWeb.Endpoint.call/2
(phoenix 1.5.3) lib/phoenix/endpoint/cowboy2_handler.ex:65: Phoenix.Endpoint.Cowboy2Handler.init/4
(cowboy 2.7.0) /Users/apple/Desktop/reactor/deps/cowboy/src/cowboy_handler.erl:41: :cowboy_handler.execute/2
(cowboy 2.7.0) /Users/apple/Desktop/reactor/deps/cowboy/src/cowboy_stream_h.erl:320: :cowboy_stream_h.execute/3
(cowboy 2.7.0) /Users/apple/Desktop/reactor/deps/cowboy/src/cowboy_stream_h.erl:302: :cowboy_stream_h.request_process/3
(stdlib 3.12.1) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
I tried @key also which didn’t work
Did you try it this way? What exactly didn’t work?
def render(assigns) do
~L"""
<h1>Hi!</h1>
<%= @key %>
"""
end
getting this
** (exit) an exception was raised:
** (ArgumentError) assign @key not available in eex template.
Please make sure all proper assigns have been set. If this
is a child template, ensure assigns are given explicitly by
the parent template as they are not automatically forwarded.
Available assigns: [:flash, :live_action, :live_module, :socket]
(phoenix_live_view 0.13.0) lib/phoenix_live_view/engine.ex:860: Phoenix.LiveView.Engine.fetch_assign!/2
(reactor 0.1.0) lib/reactor_web/live/foo_live.ex:11: anonymous fn/2 in ReactorWeb.FooLive.render/1
(phoenix_live_view 0.13.0) lib/phoenix_live_view/diff.ex:221: Phoenix.LiveView.Diff.traverse/5
(phoenix_live_view 0.13.0) lib/phoenix_live_view/diff.ex:92: Phoenix.LiveView.Diff.render/3
(phoenix_live_view 0.13.0) lib/phoenix_live_view/static.ex:284: Phoenix.LiveView.Static.to_rendered_content_tag/4
(phoenix_live_view 0.13.0) lib/phoenix_live_view/static.ex:144: Phoenix.LiveView.Static.render/3
(phoenix_live_view 0.13.0) lib/phoenix_live_view/controller.ex:35: Phoenix.LiveView.Controller.live_render/3
(phoenix 1.5.3) lib/phoenix/router.ex:352: Phoenix.Router.__call__/2
(reactor 0.1.0) lib/reactor_web/endpoint.ex:1: ReactorWeb.Endpoint.plug_builder_call/2
(reactor 0.1.0) lib/plug/debugger.ex:132: ReactorWeb.Endpoint."call (overridable 3)"/2
(reactor 0.1.0) lib/reactor_web/endpoint.ex:1: ReactorWeb.Endpoint.call/2
(phoenix 1.5.3) lib/phoenix/endpoint/cowboy2_handler.ex:65: Phoenix.Endpoint.Cowboy2Handler.init/4
(cowboy 2.7.0) /Users/apple/Desktop/reactor/deps/cowboy/src/cowboy_handler.erl:41: :cowboy_handler.execute/2
(cowboy 2.7.0) /Users/apple/Desktop/reactor/deps/cowboy/src/cowboy_stream_h.erl:320: :cowboy_stream_h.execute/3
(cowboy 2.7.0) /Users/apple/Desktop/reactor/deps/cowboy/src/cowboy_stream_h.erl:302: :cowboy_stream_h.request_process/3
(stdlib 3.12.1) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Shouldn’t it be mount/3
? https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html#c:mount/3
So.
def mount(_params, _session, socket) do
...
end
In order to catch issues like that in the future you can tag your functions with @impl
:
@impl Phoenix.LiveView
def mount(_session, socket) do
{:ok, assign(socket, key: "max")}
end
@impl Phoenix.LiveView
def render(assigns) do
~L"""
<h1>Hi!</h1>
<%= assigns.key %>
"""
end
The code above would give you a warning that mount/2
is not a callback (because you want mount/3
instead).
Just saying, @impl
does not doe anything, unless your Editor recongnizes it.
Neither will @impl Phoenix.LiveView
The compiler will warn in your terminal
1 Like
No, as Chris mentioned you do get compilation warnings (in your editor or terminal) when using @impl
. What happened in this case is that mount/3
is an optional callback, which means that even though you have @behaviour Phoenix.LiveView
(inserted for you by use Phoenix.LiveView
). So if you instead wrote your mount
function like:
@impl Phoenix.LiveView
def mount(_, socket) do
{:ok, socket}
end
Then you will get a compilation warning like:
[Warn - 8:40:50 AM] warning: got "@impl Phoenix.LiveView" for function mount/2 but this behaviour does not
specify such callback. The known callbacks are:
* Phoenix.LiveView.handle_call/3 (function)
* Phoenix.LiveView.handle_event/3 (function)
* Phoenix.LiveView.handle_info/2 (function)
* Phoenix.LiveView.handle_params/3 (function)
* Phoenix.LiveView.mount/3 (function)
* Phoenix.LiveView.render/1 (function)
* Phoenix.LiveView.terminate/2 (function)
Which is telling you that mount/2
is not a callback and mount/3
is a valid callback. Because of these types of potential errors, when I write code I always use the equivalent of @impl Phoenix.LiveView
(personally I don’t like using @impl true
).