How to get `@view_module` from a layout with Phoenix.View 1.0.0

While Phoenix.View#render/3 used to set @view_module and @view_template for us to be used within the layout.

WIth the newer Phoenix.View 1.0.0, is there a way to access this information?

From the doc and the source, it looks like this has to be repeated explicitly now :crying_cat_face: anyone knows why?

# now we need some extra lines...
Phoenix.View.render(SomeModule, "some_template", assigns
|> Keyword.merge(
  view_module: SomeModule,
  view_template: "some_template"
))

Those functions have been moved to Phoenix.Controller.view_module/view_template. The reason is because those concepts are not very clear (or very useful) in some abstractions like LiveView, so we realized it belongs upstream. I believe it was properly deprecated and there should be CHANGELOG entries. If you are not rendering from the controller, then you have to set it yourself.

1 Like

Thanks. I wish I understood better, it still seems quite strange to me that an explicit call to Phoenix.View.render wouldn’t pass along the relevant information to the layout, and this seems quite remote from LiveView.

I opened Change wording on Changelog by marcandre · Pull Request #4571 · phoenixframework/phoenix · GitHub as the only reference in the Changelog was as a deprecation when this is actually a breaking change.

The upgrade guide is sadly a gist, so no PR possible. Could we consider moving it to the repo?

1 Like

I’d like to give a +1 on this as well. I’ve wanted to make PR’s to improve the upgrade guide as well.

I created a PR for it… Import upgrade instructions from gist by marcandre · Pull Request #4585 · phoenixframework/phoenix · GitHub

1 Like

What do you use in your template now?

I have the following code

<title><%= @view_module.title(@view_template, assigns) %></title>

allowing to set a title for each page, which I now replaced by this horrible code:

<title><%= Phoenix.Controller.view_module(@conn).title(Phoenix.Controller.view_template(@conn), assigns) %></title>

In the template:

<title><%= title(assigns) %></title>

In the view module of the template:

def title(assigns) do
  module = Phoenix.Controller.view_module(assigns.conn)
  template = Phoenix.Controller.view_template(assigns.conn)
  module.title(template, assigns)
end

There’s no need to keep all that logic in the template itself.

4 Likes

Thank you!!