Páginas com títulos dinâmicos no Phoenix / Elixir

Logo depois de inaugurar este site, eu estava vendo como o conteúdo estava aparecendo nos resultados de busca do Google e percebi que eu havia deixado o title da página fixo, isto é, ele estava sempre o mesmo valor independente do conteúdo que o visitante via. E obviamente, isso era péssimo. Eu queria que o título da página mudasse conforme a matéria ou curso visualizado. Vou te ensinar a fazer isso no Phoenix.

Aviso aos tripulantes: Se você não usa o framework Phoenix do Elixir, este post não vai te ajudar.

A maneira que eu resolvi implementar a mudança de título de página é ligeiramente diferente de outras soluções que você encontra pela internet. A maioria das soluções por aí sugere que você implemente uma função page_title/2 na view e faça pattern match para cada template. Eu não gosto dessa solução e o motivo é simples: eu não a acho prática.

1. Controller

Dando uma olhada no meu controller, a solução que me veio a cabeça foi simplesmente criar uma função put_page_title tal que eu pudesse usá-la assim:

defmodule AgilsoWeb.BlogController do
  use AgilsoWeb, :controller
  alias Agilso.Blog

  def post(conn, %{"id" => id}) do
    post = Blog.get_post!(id)

    conn
    |> assign(:post, post)
    |> put_page_title(post.title) # <<<<<<< here
    |> render("post.html")
  end
end

Além disso, eu queria que quando eu não chamasse a função no controller, que aparecesse um título padrão. Foi isso que eu fiz, acompanhe.

2. Layout

No meu layout template app.html.eex, eu fiz assim:

<title><%= page_title(assigns) %></title>

e na view layout_view.ex, eu defini esta função:

defmodule AgilsoWeb.LayoutView do
  use AgilsoWeb, :view

  def page_title(assigns) do
    assigns[:page_title] || "Agilso - Expert em Internet e Posicionamento Digital"
  end

end

Em outras palavras, quando a variável "page_title" não for setada, o valor padrão assume.

3. PageTitle Module

Só falta implementar a função put_page_title do início. Para isto, eu criei um arquivo que vai funcionar como um helper dentro da pasta do controllers: lib/agilso_web/controllers/page_title.ex.

defmodule AgilsoWeb.PageTitle do

  import Plug.Conn, only: [assign: 3]

  def put_page_title(conn, page_title) do
    assign(conn, :page_title, page_title <> " - Agilso.com")
  end

end

E por fim, no seu arquivo nome_da_sua_app_web.ex, você precisa importar esse módulo para expor essa função aos seus controllers.

defmodule AgilsoWeb do
...
def controller do
    quote do
      use Phoenix.Controller, namespace: AgilsoWeb
      import Plug.Conn
      import AgilsoWeb.Gettext
      alias AgilsoWeb.Router.Helpers, as: Routes

      # Page Title Helper Module
      import AgilsoWeb.PageTitle, only: [put_page_title: 2]
    end
  end
...
end

E, acredite se quiser, é isto. :)

Até uma próxima.