LiveView render not propagating assigns if render is not ~L but a index.html.leex file?

In router.ex I have a plug that assigns some variables to app.html.ex template, one of it is @locale, while this works well in regular controllers, I noticed something that for me is strange in render function:

In live view controller, if I display html with the sigil ~L, like this, previously assigned variables are bound and available:

def render(assigns) do

However, if I use a file template (needed not to dirty the code too much with a large html) in the following form, then none of the assigns from my plugs are available, thus it generates an error:

def render(assigns) do
	AppWeb.IndexView.render("index.html", assigns)

Provided views/index_view.ex like

defmodule AppWeb.IndexView do
  use AppWeb, :view

Am I missing something so it does not work in one form but works in another?


Edit, Question related: How to access then previous assigns made by router’s plugs in the same way I can access them from a regular controller? In this case, it would be access that @locale from liveview’s html.leex

1 Like

The extension for a live view template is .leex :slight_smile:


My mistake, yes, I have a leex, sorry, will edit original post.

1 Like

Is the assign you are trying to update in app.html.eex, app.html.leex or index.html.leex?

1 Like

The assign comes from a plug defined in router.ex file, inside browser pipeline, like

pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
    plug AppWeb.Configure, gettext: AppWeb.Gettext, default_locale: "en"
    plug :put_layout, {AppWeb.LayoutView, :app}
    plug Phoenix.LiveView.Flash

As I mentioned before, in a regular controller it is not an issue to access to that assign, but it is an issue on liveview currently.

To answer your question, via ~L sigil, then app.html.leex usage of @locale works but in any way it is available for index.html.leex

I fear that I am missing something that propagates the assigns made previously to this new liveview code but I am lost in this regard.

Edit, the error I get comes with a hint that points to that direction:

But then why in a regular controller works and not in liveview mode?

1 Like

I am not sure I fully understand, but in general it seems to me that if @locale is in app.html.leex, calling AppWeb.IndexView.render to render index.html.leex is not going to pass the new assign to/trigger a re-rendering of app.html.leex.


Everything that is in the controller (such as locale) that you want to be available in your liveview you need to put it in the LiveView session. If you are setting the LiveView from your router, there is a session option where you specify which keys you want to pass through. Putting the locale in the session is a quick way to achieve that. You can also explicitly have a controller and call live_render from the controller passing everything you want in the session.


Thanks for the hint,

I’ve created a minimal testcase of this issue and uploaded on GitHub, I would be very thankful if you can take a look.

If loaded via localhost:4000/normal, a normal controller will be displayed, if loaded via localhost:4000/live a live controller will be shown, reflecting the current problem.

That @test variable is assigned by router, defined in router.ex as a plug


1 Like

As José said, you need to pass the locale to live_render, via the session:

Phoenix.Controller.live_render(conn, Mylive, session: %{local: conn.assigns.locale})

The live macro in the router only allows specifying values to copy from the conn cookie session to the LV, so you need to use the controller approach and pass your local explicitly. No assigns are shared from the conn to the LiveView mount. Check out the life-cycle docs for more info


Thank you all!

This was driving me crazy

1 Like