On occasion, however, we find ourselves in the need to add a custom page. The official documentation has a chapter detailing how to do just that, and it’s a good enough approach in 99% of our use cases.

The outlined approach works when you want to add tabular data, that is limited in size, so it can fit all on one page, and you can use built in searching / sorting features with it.

That’s great, and there are excellent blog posts out there going into the details of such set up.

In the 1% of the cases, we find ourselves in need to add something that is entirely custom. It may be a settings page or a paginated list of records, toggles for feature flags or a custom chart.

Whatever it is - you can add an entirely custom page to LiveDashboard, and here’s how.

Router and custom page module

You will need to configure the router, so that LiveDashboard loads custom page module that will wrap our page:

# lib/ui/router.ex

defmodule UI.Router do
  ...

  scope path: "/admin/dashboard" do
    pipe_through(:browser)
    pipe_through(:require_system_admin)

    live_dashboard "/",
      ecto_repos: [DB.Repo],
      additional_pages: [
        my_custom_page: UI.Live.Admin.MyCustomPage # <- add this
      ]
  end

  ...

end

And you will also need to define a module that complies with PageBuilder’s API:

# lib/ui/live/admin/my_custom_page.ex

defmodule UI.Live.Admin.MyCustomPage do
  @moduledoc false
  use Phoenix.LiveDashboard.PageBuilder

  @impl true
  def menu_link(_, _) do
    {:ok, "My Custom Page"}
  end

  @impl true
  def render_page(_assigns) do
    {UI.Live.Admin.MyCustomComponent, %{id: :my_custom_component}} # <- note this
  end
end

This custom page will add a link to the menu bar in LiveDashboard. The trick to building entirely custom LiveDashboard pages is to return tuple consisting of module name and assigns from render_page/1 function.

The assigns also need to contain :id key, as the component has to be stateful.

That’s it. Now you just need to build your custom page as stateful LiveComponent. The end!

Post by Hubert Łępicki

Hubert is partner at AmberBit. Rails, Elixir and functional programming are his areas of expertise.