Scoped live view does not seem to generate a live_path helper

Hello everyone,

I am building an app that contains two scoped areas. One for the users and one for the admins. I created two dashboard live views.

  • The first one mounted on “/”
  • The second one mounted on “/admin”

There are the codes I wrote:

  scope "/", MyAppWeb do
    pipe_through :browser

    live "/", DashboardLive
  end

  scope "/admin", MyAppWeb, as: "admin" do
    live "/", Admin.DashboardLive, as: "dashboard"
  end

Live views:

defmodule MyAppWeb.Admin.DashboardLive do
  use MyAppWeb, :live_view

  @impl true
  def mount(_params, _session, socket) do
    {:ok, assign(socket, title: "Admin Dashboard")}
  end
end
defmodule MyAppWeb.DashboardLive do
  use MyAppWeb, :live_view

  @impl true
  def mount(_params, _session, socket) do
    {:ok, assign(socket, title: "User Dashboard")}
  end
end

Templates

<div><%= Routes.live_path(@socket, MyAppWeb.DashboardLive) %></div>
<div><%= Routes.live_path(@socket, MyAppWeb.Admin.DashboardLive) %></div>

Unfortunately when I am going to / I have an error that explains me the live_path does not exist for my Admin scoped route.

When I am going to “/admin” everything works:

I am not sure if I am doing it well or if I miss something?

I created a sample repo that reproduce this “bug”: https://github.com/Malian/phoenix-live-view-scoped-path-bug

Does someone see my error or should I report a bug to the phoenix live view repository ?

Thank you!

mix phx.routes generates these routes:

live_path  GET  /                     Phoenix.LiveView.Plug MyAppWeb.DashboardLive
admin_dashboard_path  GET  /admin     Phoenix.LiveView.Plug MyAppWeb.Admin.DashboardLive

Routes.admin_dashboard_path would be the right helper method for the 2nd route.

2 Likes

Thank you for your answer.

Indeed a route helper is generated! I didn’t understand that the live_path helper is also a generated helper, the default one. I though this was a function that takes the LiveView as an argument but it wasn’t.

If I replace my code with

Routes.admin_dashboard_path(@socket, MyWebApp.Admin.DashboardLive)

it works.

But I do not understand why I have to specify the live view as I already specified it when I created the route. Do you have an explanation?

Anyway, thank you for your solution!

Imagine the following route definition:

  scope "/admin", MyAppWeb, as: "admin" do
    live "/", Admin.DashboardLive, as: "dashboard"
    live "/stats", Admin.StatsLive, as: "dashboard"
  end

These would generate the following route helpers:

admin_dashboard_path  GET  /admin         Phoenix.LiveView.Plug MyAppWeb.Admin.DashboardLive
admin_dashboard_path  GET  /admin/stats   Phoenix.LiveView.Plug MyAppWeb.Admin.StatsLive

So, you have the same path helper, admin_dashboard_path, but 2 possible results, depending on the LiveView you pass as the parameter.

You can also use actions with live routes, so it will feel more similar to traditional route helpers:

live "/articles", ArticleLive.Index, :index
live "/articles/new", ArticleLive.Index, :new
live "/articles/1/edit", ArticleLive.Index, :edit

When an action is given, the generated route helpers are named after the LiveView itself (the same as in a controller). For the example above, we will have:

article_index_path(@socket, :index)
article_index_path(@socket, :new)
article_index_path(@socket, :edit, 123)

Actions and live navigation

4 Likes

Thank you ! It’s much more clearer for me now.