In earlier versions we were using mix phx.new my_app --live and you get a batteries included app with at least one example page_live.ex show you how LiveView works, but now we came back to controllers. I need to create live folder and remove the generated controller with its test and view files
although when I created the app from the beginning I passed --live argument because I don’t want to do all of that stuff.
I am not sure actually if passing --live has any effect except in router.ex file that it inject plug :put_root_layout, {MyAppWeb.LayoutView, :root}, because I don’t see it has any effects and actually it is not written anymore in mix phx.new help and I thought because it was already included by default in any new Phoenix 1.6+ app.
When I create any liveview we used to write use MyAppWeb, :live_view which will inject all useful modules and helper functions in your LiveView and this due to the unquote(view_helpers()) in my_app_web.ex, also when creating livecomponent we write use MyAppWeb, :live_component but now we encouraged to write in first case just use Phoenix.LiveView and in second use Phoenix.LiveComponent and guess what? Many of helpers functions are not injected, all Routes.*_path_* are not defined, even live.html.heex not used by default for any LiveView and only root.html.heex layout.
For the layout issue, it is written in changelog of ver 0.16.x that:
LiveView 0.16 removes the :layout and :container options from Phoenix.LiveView.Routing.live/4 in favor of the :root_layout and :container options on Phoenix.Router.live_session/3.
BUT in documentation it is written
Note: the above assumes there is plug :put_root_layout call
in your router that configures the LiveView layout. This call is
automatically included by mix phx.new --live and described in
the installation guide. If you don’t want to configure a root layout,
you must pass layout: {MyAppWeb.LayoutView, "app.html"} as an
option to the Phoenix.LiveView.Router.live/3 macro above.
So I don’t know if I should pass :layout option for live macro or it is deprecated, and I actually tried to pass it and I got error (ArgumentError) unknown live option :layout.
I don’t know now, for every LiveView I create, I should tell it which layout should use, and alias in it alias AhramSchoolWeb.Router.Helpers, as: Routes so all routes will be defined?
There are other things concern with function components, for instance how I can use any routes inside them, again need to import helpers? How to pass socket inside them to use it for routes?
I used LiveView since ver. 0.9.x till ver. 0.15.x and I was very comfortable using it, so no one will think I am newbie for live view.
Ya I know, that’s why I am confused because it is mentioned in 0.17.x documentation that if you used --live to create your app, then it will inject in router.ex that plug. I don’t use it when I create new apps, but what about layouts problem and if we should write use MyAppWeb, :live_view or use Phoenix.LiveView??
Suppose I just want live page without context or db tables? I mean I just use phx.gen.live when I need to create resources, context or db tables.
Sure no problem to create a folder, it’s not the end of the world.
OK I also use use MyAppWeb, :live_view that’s why I say documentation is confusing because it uses use Phoenix.LiveView and I wonder how they write it like because they will lose access to live.html.heex layout and all imports and aliases written in view_helpers function in my_app_web.ex file.
@alaadahmed I was just puzzling over the :layout option to the live macro, as documented in the “Live layouts” guide today too. Digging further, It looks like the module docs got updated with the change, but the guide did not.
I am just learning Phoenix, so I was trying to figure out how to use a different root layout for a live route as opposed to the default one in the :browser pipeline.
Wrapping the live macro in a live_session with the :root_layout does the trick:
scope "/", TlWeb do
pipe_through :browser
get "/", PageController, :index
live_session :default, root_layout: {TlWeb.LayoutView, :different_layout} do
live "/exchange", FirstLive
end
end
From the live_session documentation, this appears to be acceptable.
This is useful when LiveViews require different authentication strategies or simply when they use different root layouts (as the root layout is not updated between live redirects).
OK I don’t know if this is a good practice or right way to do it, but I put this code inside my my_app_web.ex file
def component do
quote do
use Phoenix.Component
unquote(view_helpers())
end
end
And now any time I need to make Function Component, I just write:
defmodule MyAppWeb.MyFuncComponent do
use MyAppWeb, :component
def button(assigns) do
~H"""
<%= live_redirect to: Routes.live_path(@socket, :home) , class: "class-name" do %>
<%= @name %>
<% end %>
"""
end
end
So I can use Routes.*_path inside my function components if I needed to.
Yes I am aware of live_session and that it can be used to change layout, but I was struggling to use the live.html.heex which was default layout for any liveview with the new syntax used to define a liveview which is use Phoenix.LiveView because in this new syntax my liveview is not aware of any layout except the root.html.heex one because that one is defined in the router.ex file in this line plug :put_root_layout, {MyAppWeb.LayoutView, :root}.
You should still use use MyAppWeb, :live_view. If you got the impression you must not use it, please let us know, so we address it. use MyAppWeb, :live_view is generated by default from Phoenix v1.6.
The documentation is outdated. It has been fixed.
In a nutshell, --live became the default and, besides deprecations, nothing else changed. You should continue using everything the same.
For function components, you need to pass the socket and import the routes, as you would do for any other function or LiveView. Although, in the next Phoenix, we will also have a use MyAppWeb, :component for convenience. Good call on already adding it.
I use it because the injected imports that it does for me, also I used to use this syntax when I have different layouts in my template/layout folder, so I just make for example admin.html.heex and in my my_app_web.ex file I define function for it like def live_admin do ... and import inside it what I need specifically for that layout.
I thought passing socket for all type of components is deprecated, but I found that it was only for live_component, but for function component I still pass it.
Hey sorry for chiming in a bit late, but I learned this recently and it helped me out with my function components:
You don’t have to write Routes.live_path(@socket, :home) in your function components, the route helpers can instead take the Endpoint module as the first argument. You don’t actually need the socket. See the docs here: Routing — Phoenix v1.6.2
So in your example, you can just do: Routes.live_path(MyAppWeb.Endpoint, :home)
Nice tip really, now I just aliased MyAppWeb.Endpoint in my function components module and just pass Endpoint instead of each @socket and removed @socket from all assigns and code looks cleaner now. Thanks @doughsay for tip, very valuable