Playing With Fire

Exploring the web one Elixir at a time

Phoenix - Applying alternative layouts to all a controllers views

Phoenix, like many MVC frameworks provides you with a default layout to use and abuse to your hearts content.

What isn’t so clear is how to apply an alternative layout to all the views of a controller.

If you have Ruby on Rails experience changing the layout a controller uses it pretty trival.

In the head of the controller, in the simplest cast, just use the layout declaration like thus

class BlogController < ApplicationController
    layout "alternateLayout"
    ...

end

http://guides.rubyonrails.org/layouts_and_rendering.html

In Phoenix, its not quite that trivial, but its not difficult, although it isn’t really documented anywhere. What is documented is how to apply an alternative layout to individual controller actions Assigning Layouts.

As part of the Plug pipeline that every controller is piped through, one of the applied plugs is action. Phoenix.Controller

Overriding this plug is an easy way of getting custom information into the connection, things that would need to found/looked up repeatedly. The great thing about this is that the details are available to all actions within that controller only. Overriding this is not only great for applying layouts, but for a heap of other stuff including ensuring authenticated users, but that will be the subject of another post.

To do this, add the following code to your controller

def action(conn, _) do
    conn = conn |> put_layout("alternative_layout.html")
    apply(__MODULE__, action_name(conn), [conn, conn.params])
end

You will need to change the layout template name (“alternative_layout.html” in the example) to the layout that you wish to use.

Remember you will need to add this new .html.eex file to web/templates/layout/ in order for Phoenix to be able to use it.

And don’t forget to have

<%= render @view_module, @view_template, assigns %>

somewhere in the template otherwise your controller view template wont be rendered.

Until next time