How can I set a specific layout for a specific LiveView?
I have the following route:
scope "/:locale", MyAppWeb do
pipe_through :browser
live "/", LandingPageLive, :home
# some other routes
end
And this in MyAppWeb
:
def live_view do
quote do
use Phoenix.LiveView,
layout: {MyAppWeb.Layouts, :app}
on_mount MyAppWeb.SetLocale
unquote(html_helpers())
end
end
This means that by default all LiveViews have the app layout.
How can I make it so that the LandingPageLive
does not have the app layout (which contains a sidebar)?
Looking at the documentation, I see here that there are two ways to override the default layout:
- live_session which I do not have
- :layout option when mounting the LiveView.
Since I donβt have a live_session in my router, Iβm going for the second option using {MyAppWeb.Layouts, :landing_page}
:
defmodule MyAppWeb.LandingPageLive do
use MyAppWeb, :live_view
use Gettext, backend: MyAppWeb.Gettext
@impl LiveView
def mount(params, _session, socket) do
socket = assign(socket, layout: {MyAppWeb.Layouts, :landing_page})
{:ok, socket}
end
@impl LiveView
def render(assigns) do
~H"""
Welcome!
"""
end
end
And I have a the following directory structure:
lib/my_app_web/
βββ components
β βββ core_components.ex
β βββ layouts
β β βββ app.html.heex
β β βββ landing_page.html.heex
β β βββ root.html.heex
β βββ layouts.ex
β βββ sidebar.ex
βββ live
β βββ landing_page_live.ex
However, I get this error:
invalid value for reserved key :layout in Phoenix.Template.render/4 assigns.
:layout accepts a tuple of the form {LayoutModule, "template.extension"},
got: {ClipboardWeb.Layouts, :landing_page}
Looks like I need to pass a string:
defmodule MyAppWeb.LandingPageLive do
use MyAppWeb, :live_view
use Gettext, backend: MyAppWeb.Gettext
@impl LiveView
def mount(params, _session, socket) do
socket = assign(socket, layout: {MyAppWeb.Layouts, "landing_page.html"})
{:ok, socket}
end
@impl LiveView
def render(assigns) do
~H"""
Welcome!
"""
end
end
Not enough:
no "landing_page.html" html template defined for ClipboardWeb.Layouts (the module exists but does not define landing_page.html/1 nor render/2
My MyAppWeb.Layouts
looks like so:
defmodule MyAppWeb.Layouts do
@moduledoc """
This module holds different layouts used by your application.
See the `layouts` directory for all templates available.
The "root" layout is a skeleton rendered as part of the
application router. The "app" layout is set as the default
layout on both `use MyAppWeb, :controller` and
`use MyAppWeb, :live_view`.
"""
use MyAppWeb, :html
alias MyAppWeb.Sidebar
embed_templates "layouts/*"
end
Thus I assume that it embeds all templates under the lib/my_app_web/components/layouts/
.
Whatβs the expectation here?