Phoenix Page Titles

Adding titles on your page can give users extra guidance to see what they are looking at. In Phoenix, adding this can be done with only a few changes.

At first we take the base function that we are going to use to create the page title. This can be added to the AppNameWeb module within the view/0 function in the quote do ... end block. This is nice because the view function is used in all our view modules with use AppNameWeb, :view. We call the function page_title/2 and it will look like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# lib/app_name_web.ex
defmodule AppNameWeb do
  ...

  def view do
    quote do

      ...

      def page_title(_, _), do: gettext("AppName")
      defoverridable page_title: 2
    end
  end
  ...

end

Here we also see that page_title/2 is overridable which means that modules that use this module can implement their own page_title/2, thus overriding the created function and use the page_title/2 as a backup.

This function can now be called from the layout app template and that will look like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# lib/app_name_web/templates/layout/app.html.eex
<html>
  <head>
    ...

    <title><%= @view_module.page_title(@view_template, assigns) %></title>
  </head>

  ...
</html>

In this piece of code we take the given @view_module variable, which is the view module for the template of the current page, and call page_title/2. The page_title function will be given two arguments:

  • @view_template which will be something like "new.html", "edit.html" or "index.html
  • assigns which contains all the data assigned in the controller that is needed to render the page

And now the page_title/2 can be implemented in the views, for example in a user view.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# lib/app_name_web/templates/layout/app.html.eex
defmodule AppName.UserView do
  use AppNameWeb, :view
  def page_title("show.html", %{user: %User{name: name}}) do
    gettext("Profile of: %{name}", name: name)
  end

  def page_title("edit.html", _) do
    gettext("Edit your profile")
  end

  def page_title("index.html", %{users: users}) do
    count = Enum.count(users),
    ngettext("1 user in AppName",
             "%{count} users in AppName",
             count,
             count: count)
  end
end