Gulliver
Directory structure for templates in Phoenix app
How can I change the default directory structure for templates in Phoenix app?
I just tried to create a new project and added some authentication to it by doing the “mix phx.gen.auth Accounts User users”. The result worked as expected but the directory/file structure it generated was quite a mess in my opinion. All the generated templates were directly under the “templates” directory, as user_registration, user_session and so on.
So I wanted to fix this by creating a “user” subdirectory and moving all the user related templates there but I couldn’t find a place where to tell phoenix where these templates files are. The generated view files were quite empty and they all just seem to call this “view” function. So where can I tell which templates this view actually renders and where they are?
Marked As Solved
tadasajon
I just refactored a project I’m working on to address precisely this issue. I added a new function to myapp_web.ex, so now I have both view and accounts_view:
def view do
quote do
use Phoenix.View,
root: "lib/quizdrill_web/templates",
namespace: QuizdrillWeb
# Import convenience functions from controllers
import Phoenix.Controller,
only: [get_flash: 1, get_flash: 2, view_module: 1, view_template: 1]
# Include shared imports and aliases for views
unquote(view_helpers())
end
end
def accounts_view do
quote do
use Phoenix.View,
root: "lib/quizdrill_web/accounts/templates",
namespace: QuizdrillWeb
# Import convenience functions from controllers
import Phoenix.Controller,
only: [get_flash: 1, get_flash: 2, view_module: 1, view_template: 1]
# Include shared imports and aliases for views
unquote(view_helpers())
end
end
Then, I created a new accounts/ folder at lib/myapp_web/accounts/ and I created three directories inside it: controllers/, views/, templates/. So my directory structure inside myapp_web looks like this:
myapp_web/
├── accounts/
│ ├── controllers/
│ │ ├── user_auth.ex
│ │ ├── user_confirmation_controller.ex
│ │ ├── user_registration_controller.ex
│ │ ├── user_reset_password_controller.ex
│ │ ├── user_session_controller.ex
│ │ └── user_settings_controller.ex
│ ├── templates/
│ │ ├── user_confirmation/
│ │ ├── user_registration/
│ │ ├── user_reset_password/
│ │ ├── user_session/
│ │ └── user_settings/
│ └── views/
│ ├── user_confirmation_view.ex
│ ├── user_registration_view.ex
│ ├── user_reset_password_view.ex
│ ├── user_session_view.ex
│ └── user_settings_view.ex
├── controllers/
│ └── page_controller.ex
├── templates/
│ ├── dashboard/
│ │ └── index.html.heex
│ ├── layout/
│ │ ├── live.html.heex
│ │ ├── _user_menu.html.heex
│ │ ├── root.html.heex
│ │ ├── admin.html.heex
│ │ └── app.html.heex
│ └── page/
│ ├── index.html.heex
│ └── dashboard.html.heex
├── views/
│ ├── error_helpers.ex
│ ├── error_view.ex
│ ├── layout_view.ex
│ ├── page_view.ex
│ └── dashboard_view.ex
├── endpoint.ex
├── gettext.ex
├── telemetry.ex
└── router.ex
The controllers and the views can be moved into the new directories without affecting anything, but if the templates are moved then they will be in the wrong location – so I have edited each of the view files so it is an :accounts_view rather than a :view, following the adjustment I made to lib/myapp_web.ex. For example:
defmodule QuizdrillWeb.UserConfirmationView do
use QuizdrillWeb, :accounts_view
end
Now I have everything having to do with user accounts under the accounts/ directory and out of the way.
I’d appreciate any feedback, incidentally – the one thing I don’t like about this approach is the code-duplication between the view and accounts_view functions in lib/myapp_web.ex – I’d prefer to only change the root directory for the templates rather than copy-paste the whole function in the way that I did.
Also Liked
stefanchrobot
Take a look at the options taken by use Phoenix.View.
See here: Liveview conventions, Why put liveview template in live folder? - #7 by stefanchrobot
APB9785
The view function is in lib/my_app_web.ex:
def view do
quote do
use Phoenix.View,
root: "lib/my_app_web/templates",
namespace: MyAppWeb
# Import convenience functions from controllers
import Phoenix.Controller,
only: [get_flash: 1, get_flash: 2, view_module: 1, view_template: 1]
# Include shared imports and aliases for views
unquote(view_helpers())
end
end
You can define other alternatives to view here and use them instead when needed.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








