0
votes

I found a clause in 'app.html.eex' auto-created by elixir phoenix:

<main role="main">
   <%= render @view_module, @view_template, assigns %>
</main>

but where is this keyword map 'assigns' coming from?

2
In your controller, when you do render conn, "index.html", key: :value, the assigns will be populated with the key: :value pair, as well as anywhere you call assign(conn, :other_key, :other_value). The actual assigns are held in the conn. You just get convenient access to them in the templates. - Justin Wood
@JustinWood I know, but this app.html.eex is auto-generated by phoenix itself, I am wondering where this variable assigns is coming from. It must be somewhere in the source code of phoenix. - chenyuandong
Are you asking where in the phoenix library code it generates the assigns variable? Because that reads differently from your question. - Justin Wood
assigns just refers to conn.assigns. Unless I am misunderstanding the question? - Dan
@JustinWood Yes, I'm asking where assigns variable is from phoenix library. Thx. My bad. - chenyuandong

2 Answers

1
votes

assigns is a template-context local variable declared via hygiene bypassing in the template compile-time.

0
votes

per the docs Phoenix.View.hmtl

Assigns

"Assigns are meant to be user data that will be available in templates. However, there are keys under assigns that are specially handled by Phoenix, they are:

:layout - tells Phoenix to wrap the rendered result in the given layout. See next section. The following assigns are reserved, and cannot be set directly:

@view_module - The view module being rendered @view_template - The @view_module’s template being rendered "

assigns is a property on the conn object designed to add data to pass around like options.

assigns itself is coming @conn.assigns, in any controller you can play around with this by adding this code to a controllers index

defmodule MyAppWeb.PageController do
  use MyAppWeb, :controller

  def index(conn, _params) do
    conn = assign(conn, :thing, "this is not a taco")
    render conn, "index.html"
  end
end

then in app.html.eex add this line

<%= assigns.thing %>

then you should see "this is not a taco" when you hit the controllers index, "/" in this example

if you add this line to your controller you can see it in your server

...
    conn = assign(conn, :thing, "this is not a taco")
    IO.inspect(conn.assigns)
...

I have most commonly seen this used to set a user to assigns to have access in the views like this ...plugs/set_user

 def init(_params) do
 end

 def call(conn, _params) do
    if conn.assigns[:user] do
      conn
    else
      user_id = get_session(conn, :user_id)

      cond do
        user = user_id && Repo.get(User, user_id) ->
          assign(conn, :user, user)
        true ->
          assign(conn, :user, nil)
      end
    end
 end

...view/html

  <%= if @conn.assigns.user do %>
      Hello, <%= @conn.assigns.user.first_name %>!       
  <% else %>
  ... do something else
  <% end %>

to assign value you use 'assign'

to get the values you use 'assigns'

docs on Plug.conn