Multiple root layouts in Phoenix?

On this page of the Phoenix documentation: Components and HEEx — Phoenix v1.8.5

It talks about layouts and the root layout. But I cannot find anywhere on the site on how to use alternate “root” layouts like: root1, newTeamplateView, etc…

Am I to understand that the app only gets one root layout and we define the enclosing “templates” in layouts.ex?

Can we do stuff like:

plug :put_root_layout, html: {HelloWeb.Layouts, :admin}

in the view?

You can set it in controllers by put_layout Phoenix.Controller#put_layout .edit: Also Phoenix.Controller#put_root_layout, to be honest I have never used either of these that I can recall.

For liveviews you can adjust the root layout by:

You can set the app layout (rendered inside the root layout) in Liveviews by adjusting the call to use Phoenix.LiveView with a layout: {Mod, :name}. Phoenix.LiveView — Phoenix LiveView v1.1.28 . So you can do it “per” live view. Normally this call is wrapped up in your my_app_web.ex, in the def live_view macro, which is then run in your liveviews by use MyAppWeb, :live_view.

How I have handled this, at least in lv0.20 and phx1.7 (I know these are old but I dont think the layout infra has changed since) is plug calls in the router and my own “aspects” in MyAppWeb. Generally I haven’t wanted “just one view” to use a different layout, so bundling them by the router + use :my_x_live_view is how I’ve done it.

# router.ex
pipeline public do
  plug :browser
  plug :put_root_layout, {Public.Layouts, :root}
end

pipeline admin do
  plug :browser
  plug :put_root_layout, {Admin.Layouts, :root}
  # Note that plug can be `module, arg` too, so you could probably wire up
  # plug Admin, :default_root_layout
  # plug Admin, {:use_layout, :x}
  # etc
end

pipeline admin_printable do
  plug :browser
  plug :put_root_layout, {Admin.Layouts, :printable}
end


scope ... do
  pipe_through :public
  # ...
end

scope ... do
  pipe_through :admin
  # ...
end
# my_app_web.ex
# ...

# usage `use MyAppWeb, :admin_live_view`
def admin_live_view do
  quote do
    use Phoenix.LiveView, layout: {Admin.Layouts, :app}
    # ...
  end
end

# etc ...

Edit:

Can we do stuff like: plug :put_root_layout, html: {HelloWeb.Layouts, :admin} in the view?

You cant set it in “views” AFAICR as views are sort of a step removed, theyre just functions that return heex/html. You set it in the context above, controller or lv, as shown. I guess in a controller, calling put_root_layout in a function/action would effectively set it “for that view”.

2 Likes

I made a short video on using multiple layouts in Phoenix 1.8 that may help: Multiple Layouts in Phoenix 1.8 - ElixirCasts

2 Likes

This is what works and what I was looking for:

conn
|> assign(:product, answer)
|> put_root_layout(html: {UdemyPhoenixWeb.Layouts, :bird})
|> render(:bird)

Thank you all.

2 Likes