legoblocks
legoblocks

Reputation: 595

Elixir Phoenix: one does not simply generate a link

I can't seem to get the link function to be found, when using it in heex.

index.html.heex

            <%= link to: "/numbers/#{number.id}/messages", class: "block w-full h-full" do %>
              Go
            <% end %>

controllers/number_html.ex

defmodule MyApp.NumberHTML do
  use MyAppWeb, :html

  import Phoenix.HTML # This line doesn't fix it

  embed_templates "number_html/*"

end

Here's the error I get:

Compiling 1 file (.ex)
    error: undefined function link/2 (expected MyApp.NumberHTML to define such a function or for it to be imported, but none are available)
    │
 18 │             <%= link to: "/numbers/#{number.id}/messages", class: "block w-full h-full" do %>
    │                 ^^^^
    │
    └─ (my_app 0.1.0) lib/my_app/controllers/number_html/index.html.heex:18:17: MyApp.NumberHTML.index/1

I must be missing something simple.

Upvotes: -1

Views: 130

Answers (1)

David Maze
David Maze

Reputation: 158647

In phoenix_html 4.0, a number of HTML-generation functions were removed from the core. These moved into a new phoenix_html_helpers library, including PhoenixHTMLHelpers.Link.link/2. An easy approach is to take the workaround described in the phoenix_html changelog and

  1. Add a dependency in mix.exs on
    {:phoenix_html_helpers, "~> 1.0"}
    
  2. Import those in your my_app.ex view helpers
    import Phoenix.HTML
    import Phoenix.HTML.Form
    use PhoenixHTMLHelpers
    

phoenix_live_view 0.18 added a number of corresponding Phoenix components that replace these, so in the more modern stack you'd use <.link to={...} /> rather than <%= link to: ... %>. You again probably need to add the newer helpers to your my_app.ex view helpers

use Phoenix.Component

and then your HEEx template changes to use the newer component syntax

<.link to={"/numbers/#{number.id}/messages"} class: "block w-full h-full">
  Go
</.link>

If you also adopt the newer verified routes setup and your model object implements the Phoenix.Param protocol (which includes any struct with an id field), it would look a little more like

<.link to={~p"/numbers/#{number}/messages"} class: "block w-full h-full">
  Go
</.link>

Upvotes: 3

Related Questions