Gulliver

Gulliver

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?

Showing Posts 1 to 5

APB9785

APB9785

Creator of ECSx

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.

tadasajon

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.

stefanchrobot

stefanchrobot

Since I have both a server-side rendered app and an API for a mobile app in my app, I took it one step further and created separate MyAppWeb modules, something along the lines of:

defmodule MyAppWeb.App do
  # ...

  def view do
    # import HTML helpers
  end 
end

defmodule MyAppWeb.MobileApi do
  # ...

  def view do
    # import API-related helpers
  end 
end

and then:

defmodule MyAppWeb.App.SessionView do
  use MyAppWeb.App, :view

  # ...
end

defmodule MyAppWeb.MobileApi.MessageView do
  use MyAppWeb.MobileApi, :view

  # ...
end
Gulliver

Gulliver OP

Thanks, this does solve the issue. However, it seems like such an overkill to to change my whole code structure just to get some sanity in the directory sorting that I decided to get rid of the whole frontend part of Phoenix and only use it for the api and use React for the frontend. There’s seems to be bit too much magic happening with all of the rendering/templates part to my liking. Anyways, thanks for the help!

— All posts loaded —

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews