Feat: Split `counter.ex` into a basic `LiveView` Component
nelsonic opened this issue · comments
At present the counter.ex
file contains the following render
function:
Todo
-
Split this out into it's own
LiveView
Component -
Also tidy this appearance:
Please Note: there's no urgent need to do this work ...
The reason I'm doing this split here in thecounter
(the simplest possibleLiveView
app)
is so that I can learn howLiveView Components
work from first principals for: dwyl/mvp#141 (comment)
Not quite there yet ...
[error] #PID<0.677.0> running Phoenix.Endpoint.SyncCodeReloadPlug (connection #PID<0.676.0>, stream id 1) terminated
Server: localhost:4000 (http)
Request: GET /
** (exit) an exception was raised:
** (KeyError) key :val not found in: %{
id: "counter",
socket: #Phoenix.LiveView.Socket<
id: "phx-F3ZKa8Lfq1vDggPh",
endpoint: CounterWeb.Endpoint,
view: CounterWeb.Counter,
parent_pid: nil,
root_pid: nil,
router: CounterWeb.Router,
assigns: #Phoenix.LiveView.Socket.AssignsNotInSocket<>,
transport_pid: nil,
...
>,
__changed__: %{id: true, flash: true},
flash: %{},
myself: %Phoenix.LiveComponent.CID{cid: 1}
}
(counter 1.7.7) lib/counter_web/live/counter_component.ex:8: anonymous fn/2 in CounterComponent.render/1
(phoenix_live_view 0.19.5) lib/phoenix_live_view/diff.ex:386: Phoenix.LiveView.Diff.traverse/7
(phoenix_live_view 0.19.5) lib/phoenix_live_view/diff.ex:711: Phoenix.LiveView.Diff.render_component/9
(phoenix_live_view 0.19.5) lib/phoenix_live_view/diff.ex:657: anonymous fn/5 in Phoenix.LiveView.Diff.render_pending_components/6
(elixir 1.15.4) lib/enum.ex:2510: Enum."-reduce/3-lists^foldl/2-0-"/3
(stdlib 5.0.2) maps.erl:416: :maps.fold_1/4
(phoenix_live_view 0.19.5) lib/phoenix_live_view/diff.ex:629: Phoenix.LiveView.Diff.render_pending_components/6
(phoenix_live_view 0.19.5) lib/phoenix_live_view/diff.ex:143: Phoenix.LiveView.Diff.render/3
(phoenix_live_view 0.19.5) lib/phoenix_live_view/static.ex:252: Phoenix.LiveView.Static.to_rendered_content_tag/4
(phoenix_live_view 0.19.5) lib/phoenix_live_view/static.ex:135: Phoenix.LiveView.Static.render/3
(phoenix_live_view 0.19.5) lib/phoenix_live_view/controller.ex:39: Phoenix.LiveView.Controller.live_render/3
(phoenix 1.7.7) lib/phoenix/router.ex:430: Phoenix.Router.__call__/5
(counter 1.7.7) lib/counter_web/endpoint.ex:1: CounterWeb.Endpoint.plug_builder_call/2
(counter 1.7.7) deps/plug/lib/plug/debugger.ex:136: CounterWeb.Endpoint."call (overridable 3)"/2
(counter 1.7.7) lib/counter_web/endpoint.ex:1: CounterWeb.Endpoint.call/2
(phoenix 1.7.7) lib/phoenix/endpoint/sync_code_reload_plug.ex:22: Phoenix.Endpoint.SyncCodeReloadPlug.do_call/4
(plug_cowboy 2.6.1) lib/plug/cowboy/handler.ex:11: Plug.Cowboy.Handler.init/2
(cowboy 2.10.0) /Users/n/code/phoenix-liveview-counter-tutorial/deps/cowboy/src/cowboy_handler.erl:37: :cowboy_handler.execute/2
(cowboy 2.10.0) /Users/n/code/phoenix-liveview-counter-tutorial/deps/cowboy/src/cowboy_stream_h.erl:306: :cowboy_stream_h.execute/3
(cowboy 2.10.0) /Users/n/code/phoenix-liveview-counter-tutorial/deps/cowboy/src/cowboy_stream_h.erl:295: :cowboy_stream_h.request_process/3
Got it working. Just had to pass the val={@val}
into the LiveView Component
.
But have the following warnings:
warning: conflicting behaviours found. function handle_event/3 is required by Phoenix.LiveComponent and Phoenix.LiveView (in module CounterComponent)
lib/counter_web/live/counter_component.ex:1: CounterComponent (module)
warning: conflicting behaviours found. function render/1 is required by Phoenix.LiveComponent and Phoenix.LiveView (in module CounterComponent)
lib/counter_web/live/counter_component.ex:1: CounterComponent (module)
May I ask why you would create a "sub LiveView"? I understand that the counter is already a LiveView, the unique one, so it comes with its own state and handlers. Isn't it redundant to create a "sub LivevVew" with the exact same state? Or I might have not understood your intention!
@ndrean great question. Apologies if the context is not clear from the OP.
The goal is not to complicate this
project.
I'm adding an optional section in this tutorial to introduce LiveView Components
.
The idea is to intro the topic in the most basic App, a counter
.
Then I intend to apply this knowledge over in the MVP
where is relevant to split out the Components
. 👌
ok ok . Maybe the button could be a component? you could probably use <Button.display click="inc"/>
in the LiveView for example with the Phoenix.Component
attr :click, :string, required: true
def display(assigns) do
~H""" <button phx-click={@click}><%= @click %></button> """
end
Totally. There are additional opportunities for splitting out out further. PRs welcome. 👌
I'm just wrapping up the docs on this and updating the links to the Fly.io App. 🔗