26

I have two template folder in my web/templates folder:

> ls web/templates
personal_info       user

What I want is to render some template from user folder in another view of personal_info. so I have a file at path: web/templates/personal_info/index.html.eex, I have following content:

<%= render "user/xyz.html" %>

But I get following error:

[error] #PID<0.821.0> running MyApp.Endpoint terminated
Server: localhost:4000 (http)
Request: GET /
** (exit) an exception was raised:
    ** (Phoenix.Template.UndefinedError) Could not render "user/xyz.html" for MyApp.PersonalInfoView, please define a matching clause for render/1 or define a template at "web/templates/personal_info". The following templates were compiled:

* index.html

Please tell me how do I render template defined in other folder, I tried few permutations, but none worked.

Saurabh
  • 71,488
  • 40
  • 181
  • 244
  • See https://hexdocs.pm/phoenix/views.html#sharing-views-and-templates in the guides. The link above and some of the answers are outdated. – tomr Jan 02 '21 at 14:31

5 Answers5

41

Phoenix templates are just functions, so when you want to render your UserView's "xyz.html" template from your PersonalInfo's view, you just call the function!

Let's say you are inside the web/templates/personal_info/show.html.eex template. (Phoenix.View.render is already imported for you):

<%= render UserView, "xyz.html", user: user %>

Of if you want to pass along all the template assigns that your PersonalInfo template was provided:

<%= render UserView, "xyz.html", assigns %>

As you found, this works from anywhere, because templates are Just Functions. For example, the same thing would work in iex:

iex> Phoenix.View.render(MyApp.UserView, "xyz.html")
"<h1>User ..."
Chris McCord
  • 8,020
  • 1
  • 37
  • 26
  • 3
    On Phoenix 1.3.0, I had to add `alias MyApp.UserView` into `web/views/personal_info_view.ex` or else it'll say `(module UserView is not available` – owyongsk Sep 05 '17 at 05:20
  • @owyongsk where is this file now? It looks like it no longer exists past phoenix 1.3.0? – sf8193 May 26 '19 at 04:06
4

As of Phoenix 1.5.1

Phoenix matches controllers, views, and templates by names. It can be changed by put_view like:

conn
  |> put_view(MyAppWeb.SpecialView)
  |> render(:show, message: "Hello")

https://hexdocs.pm/phoenix/Phoenix.Controller.html#render/3-views

Wojciech Bednarski
  • 6,033
  • 9
  • 49
  • 73
2

For me worked when I specified application name:

web/templates/product_gallery/index.html.eex:

<p>Please, render me!</p>

web/templates/kitchen/index.html.eex:

<%= render APP.ProductGalleryView, "index.html", assigns %>

If I am trying to render without application name I am getting:

undefined function ProductGalleryView.render/2 (module ProductGalleryView is not available)
Denis
  • 21
  • 2
  • In your `lib/web/views/kitchen_view.ex`, you can also add `alias APP.ProductGalleryView` so you can just use render ProductGalleryView – owyongsk Sep 05 '17 at 05:18
2

I'm on Phoenix 1.3.0. Seems like I had to add

alias MyApp.Userview

to web/views/personal_info_view.ex, then

<%= render conn, UserView, "xyz.html" %>

Without the alias above, then you have to

<%= render conn, MyApp.UserView, "xyz.html" %>    
owyongsk
  • 2,349
  • 1
  • 19
  • 21
1

Apparently following worked:

<%=  Phoenix.View.render(MyApp.UserView, "xyz.html") %>

please let me know, If there are better alternatives.

Source: this.

Saurabh
  • 71,488
  • 40
  • 181
  • 244