5
votes

I'm trying to understand the difference between the different render functions in Phoenix. Specifically, I notice there are several different render functions in a Phoenix View and a Phoenix Template.

For example, within a Phoenix Controller, it's common to see something like this:

# assume this is UserController
def index(conn, _params) do
    users = Repo.all(Users) # let's assume that this gives you all your users
    render conn, "index.html", users: users
end

Within the index.html template associated with this View (i.e. UserView), you can see something like this:

# index.html
<ul>
    <%= for user <- @users do %>
        <li><%= render "user.html", user: user %></li>
    <% end %>
</ul>

# user.html
<p><%= @user.name %></p>

My understanding is that the render function inside of the index.html template is compiled to a render function inside of the UserView. Also, after digging around in iex, it seems like the render function in the UserController's index action comes from Phoenix.Controller.render/3.

However, I notice that inside of the default app.html.eex template file, there's a render function that looks like this:

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

This doesn't seem to match the signatures of the previous render functions. Can anyone help explain where this render is coming from and how it works?

2

2 Answers

1
votes

Phoenix.View has a descriptive documentation, and if still in doubt, there is a source code for Phoenix.View.render/3 and Phoenix.Controller.render/{1,3,4} on hand.

The related quote from the documentation:

This inner representation allows us to render and compose templates easily. For example, if you want to render JSON data, we could do so by adding a “show.json” entry to render/2 in our view:

defmodule YourApp.UserView do
  use YourApp.View    
  def render("show.json", %{user: user}) do
    %{name: user.name, address: user.address}
  end
end
1
votes

The Phoenix.Controller.render/4 is passed the conn struct which picks up a number of things like overriding the layout, the view, plash messages, assigns, etc. So, you will see render called that way in controllers.

The render "templ.html", opts version renders the template of the same View of the caller. This can be used from a template to render a partial.

The Phoenix.View.render App.MyView, "templ.html", opts is used to render a template from a different view. That is why its called that way from the layout template.

They all end up calling the App.MyView.render/2. If you have templates then those functions will exist. But you can create your own render function in the view and call it as was pointed out in the answer with the json example.