Compartmentalizing code within root template

Hello,

I am starting a new app and would like to have separate templates for header, main_body and footer sections. The main_body will be live, but header and footer don’t need to be. I have been reading the documentation and it is still not clear to me how to do it because the documentation talks about Phoenix.Components, which are in fact LiveView components as I understood it…and live view components can’t be in root.

I want to do this primarily for maintainability reasons, and having nice seaparate files which are then injected into root, so that root is not crammed with bunch of stuff but looks something like this

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
  </head>
  <body>
    <.header />
    <div>
      <%= @inner_content %>
    </div>
    <.footer />
  </body>
</html>

How can I do it and where in the project tree structure should those modules and templates be placed?

You can put a Phoenix.Component in any template, even a “dead” view. Personally I would prefer to do it with components over traditional template “partials”. As for where you put your components, there is no official guideline (a lot of project structure is up to you and Phoenix does not impose conventions) but my opinion is a directory called lib/app_web/components/, and group components into modules by related functionality in your app e.g.

# in lib/app_web/components/app_shell.ex

defmodule AppWeb.Components.AppShell do
  use AppWeb, :component

  def header(assigns) do
    ~H"""
    header stuff
    """
  end

  def footer(assigns) do
    ~H"""
    footer stuff
    """
  end
end
1 Like

Thank you!
I was confused by this Phoenix.Component — Phoenix LiveView v0.17.10 in the documentation.

This works nicely. :slight_smile:

1 Like

I totally see how that can be confusing, maybe they would accept a PR to make the documentation more clear around that!