Subscribe to access all episodes. View plans →

#105: How to Create Nested Phoenix Templates

Published October 31, 2019

Elixir 1.8

Phoenix 1.4

Often as an application gets bigger, the number of templates you have grows too. When this happens you may want to organize them to make them easier to manage. In our application here, we’re starting to have that problem. If we open our “page” templates directory. We see there are a few different partial files for each “section” and as we add more sections, we’ll use another partial. Let’s organize these a little better.

We could set up a separate view and that would be a good idea if we wanted to use these partials across many different views. However, our partials here are specific to this view and wont be shared.

Instead let’s organize these partials by creating a nested directory here called “sections” since it will store the different sections for this page. Then let’s move all our partials into the new directory. Since they’re in a new location, we need to go open our “index.html.eex” template and update how we’re calling them.

Template path: lib/teacher_web/templates/page/index.html.eex

<%= render "sections/section_1.html" %>
<%= render "sections/section_2.html" %>
<%= render "sections/section_3.html" %>

Now if we go back to the browser we get an error that Phoenix could not render our new partials. By default Phoenix doesn’t compile templates in nested directories. Let’s update our application to precompile all templates in the view including ones in nested directories.

To do that we can use the Phoenix.View “pattern” option. We’ll open our teacher_web.ex module and in our “view” block let’s add the “pattern” option, giving it a pattern to compile any templates in nested directories.

lib/teacher_web/ex...def view do  quote do    use Phoenix.View,       root: "lib/teacher_web/templates",      namespace: TeacherWeb,      pattern: "**/*"...

Then if we go back to the browser and reload our page - it works. Our all our templates - even those in subdirectories - can now be called.