How to alias a view to call "render(....)" inside an html page?

In an html page I try to:

    <%= render(MyPageView, "my_page1.html") %>

Can’t render <%= render(MyPageView, "my_page1.html") %> because isn’t MyPageView is unavailable. But I’d already added

  alias MyApp.MyPageView 

to an appropriate controller.

Why can’t it find it? How to fix it?

You probably want to write:

  alias MyAppWeb.MyPageView

I’m almost sure that’s it. It happens when you are copying some module in other namespace and then you are aliasing it by hand having in mind standard alias … At least I have made such mistake few times …

As far as I can remember, you need to add the alias to the view-module responsible to render the template.

2 Likes

I did that. Here in the question this is a typo.

What alias? Alias of a module to that very module? This won’t work

defmodule MyAppWeb.MyPageView
  alias MyAppWeb.MyPageView
end

The template you are rendering and where you want to call render in, that belongs to a view, and in that view you need to alias.

1 Like

To alias where?

controller

  defmodule MyAppWeb.MyHomeController do
    alias MyAppWeb.MyHomeView


    def index(conn, params) do
      render(conn, "index.html")
    end
  end

html “home/index.html.eex”:

    <%= render(MyAppWeb.MyHomeView, "_test1.html", data: [1, 2, 3]) %>

Doesn’t work - module MyAppWeb.MyHomeView not found

That’s because templates are compiled into the *View module, not the *Controller module. Put the alias in your *View module. Remember that each template file because another render/2 case in the render/2 function that is in the *View modules. :slight_smile:

1 Like

Yep! I do it quite a lot for my helper modules. ^.^

What issue were you having?

Because templates compile as render/2 function calls inside your View module. :slight_smile:

Literally, compiling a file like my_templates/index.html.eex that contains <blah><%= @i %> </blah> compiles into your view file like:

defmodule MyView do

  ... other stuff

  def render("index.html", assigns) do
    ~E"""
    <blah><%= assigns[:i] %> </blah>
    """
  end

  ... more stuff
end

Then please show us a minimal project that causes the error.

1 Like

I wonder if i can help, but first: It sounds like you’re using Phoenix, but the code doesn’t look like you’re using Phoenix. When i create a new phoenix project my controllers need to include
use <namespace>Web, :controller
so that the Phoenix.Controller.render/3 function becomes available.

(That means my simple controller looks like this:

defmodule T21517Web.HomeController do
  use T21517Web, :controller

  def index(conn, _params) do
    render(conn, "index.html")
  end
end

, where the namespace for the modules would of course differ in your case.)

The same way your view module should have a
use <namespace>Web, :view

Then i added the function clause you seem to want to include:

def render("_test1.html", %{data: data}) do
  # I'm just returning some text here...
  "My data: #{inspect(data)}"
end

so my whole view module looks like this:

defmodule T21517Web.HomeView do
  use T21517Web, :view

  def render("_test1.html", %{data: data}) do
    "My data: #{inspect(data)}"
  end
end

And now i can call this new <namespace>Web.HomeView.render/2 clause from within my template:

<h1>Home</h1>

<%= render("_test1.html", data: [1, 2, 3]) %>

I did not include the view module as a parameter to render/2, because as @OvermindDL1 pointed out the template is “in the context of the view module”, so you can just call the render method directly.

If i missunderstood what you’re trying to do i can also imagine you wanting to call another view from within your home view. In my test i created a view module T21517Web.BlaView:

defmodule T21517Web.BlaView do
  use T21517Web, :view

  def render("bla.html", %{data: data}) do
    "This is Bla's data: #{inspect(data)}"
  end
end

and in my template for the home view i added a call to the render function from that new module:

<h1>Home</h1>

<%= render("_test1.html", data: [1, 2, 3]) %>

<%= render(T21517Web.BlaView, "bla.html", data: [4, 5, 7]) %>

Everything seems to work fine for me:

1 Like