LiveView 0.17.x really confuses me :(

I am really confused since version 0.17.x

  • 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.

1 Like

–live is the default now, and You should not use it when creating a new project.

The page_controller is now a normal controller by default.

Using mix phx.gen.live… will build the live folder, and add some helper files.

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.

Nothing stop You from creating live folder manually, and add your live page.

But as a learning experience, I created a live resource in a test project, to see what was created.

And I did not see problem with default layout, and I use

use MyAppWeb, :live_view

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).

1 Like

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.

1 Like

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}.

It has no effect. --live is the default now.

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.

6 Likes

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.

Thanks a lot @josevalim

Yup, that’s also how I would do it.

Ah, good point. The live components have access to socket (because they are “live”), function components do not.

1 Like

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)

5 Likes

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 :slight_smile:

1 Like